代码改变世界

汤姆大叔送书, 咱也科学抢书之Python版

2012-10-22 18:36  wid  阅读(3041)  评论(13编辑  收藏  举报

  

  我觉得@鲜宏 说的对, "咱是程序员,抢书也得科学", 下午3点多登录到博客园看到@汤姆大叔 的火爆送书场面还有@鲜宏 的自动抢书工具时, wid也开始琢磨写个自动抢书的脚本, 经过将近2个小时的努力, Python版的抢书工具也终于成型了, 开始进入正题。

 

·在写这个脚本时wid所使用的相关环境介绍:

  语言: Python (v2.6)

  IDE: PyScripter

 

·算法原理介绍:

  抢评的原理是根据手机版的评论工具对汤姆大叔送书的那篇随笔进行评论, 嘿嘿~反正大叔没有说来自手机评论的不算, 用手机模式评论, 提高灵活度嘛, 对不。

 

  第一步: 模拟浏览器登录到博客园, 进行带cookies的页面浏览;

  第二步: 首先从手机模式的某一个评论页面抓取数据进行分析, 之所以要抓取其中一个评论页面是因为在手机上的评论默认是显示第一页, 而不是最后一页, 并且没有直接到达最后一页的链接, 当这个页面的评论达到30条后就继续顺着页面向下找, 一直找到最后一个页面, 也就是最新的评论页面。

  第三步: 获取最新页面的评论条数, 在手机模式下的博客园评论每页至多现在30条, 当最新页面的评论条数不足30条时使用正则表达式获取该页所有评论的发表时间;

  第四步: 判断, 当获取到的最后一条评论的分钟数为59, 并且在 10, 12, 14, 16, 18, 20这个幸运小时数内, 执行倒计时60秒评论, 具体倒计时多少秒可以根据自己估算的误差进行调节, 评论完成后等待55分钟准备下一轮的抢书.

 

看具体代码:

 

#!/usr/bin/python
#-------------------------------------------------------------------------------
# Name:        GrabBook.py
# Purpose:
#
# Author:      Mr.Wid
#
# Created:     22-10-2012
# Copyright:   (c) Mr.Wid 2012
# Licence:     GNU GPL
#-------------------------------------------------------------------------------

import re
import time
import urllib
import urllib2
import httplib
import cookielib

username = 'mr_wid'             #这里是你的用户名, 改成自己的
password = 'xxxxxxxx'           #你的密码

#先定义好编码转换函数
def en(x):
    return x.encode('utf-8')

def cn(x):
    return x.decode('utf-8')

#登录博客园
def cnblogs_login():
    """登录博客园
    cnblogs_login() -> None
    """
    params_post = urllib.urlencode({
        '__EVENTTARGET': '',
        '__EVENTARGUMENT': '',
        '__VIEWSTATE': r'/wEPDwULLTE1MzYzODg2NzZkGAEFHl9fQ29udHJvbHNSZXF1aXJlUG9zdEJhY2tLZXlfXxYBBQtjaGtSZW1lbWJlcm1QYDyKKI9af4b67Mzq2xFaL9Bt',
        '__EVENTVALIDATION': r'/wEWBQLWwpqPDQLyj/OQAgK3jsrkBALR55GJDgKC3IeGDE1m7t2mGlasoP1Hd9hLaFoI2G05',
        'tbUserName':en(username),
        'tbPassword':en(password),
        'btnLogin':en('登录')
  })
    cookie=cookielib.CookieJar()
    opener=urllib2.build_opener(urllib2.HTTPCookieProcessor(cookie))
    urllib2.install_opener(opener)
    login_response=urllib2.urlopen('http://passport.cnblogs.com/login.aspx?',params_post)

#给大叔发表一条评论
def PuhsishContent( content ):
    """给大叔发表一条评论
    PuhsishContent( string content ) -> None
    """
    comment_post = urllib.urlencode({
        '__VIEWSTATE':en('/wEPDwUJNDYwODU2NjU1ZGQ='),
        'txbComment': en(content),
        'btnSubmint': en('提交评论')
    })
    page = urllib2.urlopen( r'http://m.cnblogs.com/mobileAddComment.aspx?id=101461&entry=2733027', comment_post )
    data = page.read()
    page.close()
    print cn( data )

#正则表达式获取服务器时间, 实际上是获取最后一个评论的时间
def GetServerTime( lastPage ):
    reTime = re.compile( r'(\d.\:\d.)' )
    data = urllib2.urlopen( r'http://m.cnblogs.com/101461/comments/2733027.html?p=%s'%lastPage )
    txt = data.read()
    return reTime.findall(txt)

#开始抢书啦~
def PuhsishContentInTime():
    luckHour = [ 10, 12, 14, 16, 18, 20 ]   #这是幸运小时数
    lastPage = 71                           #假设最新的评论页面为71, 这个不太重要, 为只要不超过最新的评论页面程序都会自动找到最新的评论页面
    cnblogs_login()                         #登录博客园
    while True:
        timeList = GetServerTime(lastPage)  #获取最新评论时间列表
        if len(timeList) >= 30:             #当该页的评论数超过30条数评论页面自动向下跟进
            lastPage += 1
            continue
        currentHour = int( timeList[len(timeList)-1][:2] )      #获取最新评论的小时数
        currentMinute = int( timeList[len(timeList)-1][3:] )    #获取最新评论的分钟数
        print currentMinute
        if currentHour in luckHour and currentMinute == 59:     #当最新评论的分钟数为59时开始进入倒计时抢书
            for i in range(60):
                i += 1
                time.sleep(1)
                print '抢书进入倒计时:%d秒'%( 60 - i )
            PuhsishContent( '大叔我来抢书啦~抢抢抢抢抢......' )
            print '抢书任务完成, 下一轮抢书任何将在55分钟后自动执行, 等待...'
            time.sleep(55 * 60)             #休息55分钟, 汤姆大叔说了, 连评无效


#执行抢书动作
PuhsishContentInTime()          #挂这慢慢抢吧, 挂三天说不定就...?

 

 

·不足之处

  本段代码最大的不足之处就是依然无法获取服务器的准确时间, 要是能获取准确的服务器时间那岂不是..? 嘿嘿~  还有一点就是当59分钟时如果没人评论, 而是都是抢着直接从00开始评, 那这段代码就无效了, 解决的方案也很简单, 如果59分钟时真没人评论, 可以根据本地时间作出发出的评论响应, 还可以多设几处监测点进行判断, 这里有兴趣的朋友可以自行实现, wid在这就不再多说了。 代码写的匆忙, 相关的异常捕获之类的也没有进行, 代码也有不规范之处, 还望大家多多指点!

 

本段代码的优点就是抢书的人越多, 换句话说或者是数字59出现的越准确, 抢到书的可能性就越大, 根据现场的勘查, 59分钟时发出的评论那是相当多啊...!

笔者虽说写了这段代码, 但是实际的抢书效果还没有测试, 仅仅是做了下简单的实验, 更完善的抢书方案, 期待您的发布!

 

最后, 感谢汤姆大叔给了大家一个免费学习JavaScript的机会, 谢谢!


--------------------

wid, 2012.10.22