如何通过python爬虫来全自动抢微博红包?!

作者:admin

IDF实验室 http://blog.idf.cn/2015/02/programming-of-grabing-red-envelopes/

背景大家都懂的,要过年了,正是红包满天飞的日子。正巧前两天学会了Python,比较亢奋,就顺便研究了研究微博红包的爬取,为什么是微博红包而不是支付宝红包呢,因为我只懂Web,如果有精力的话之后可能也会研究研究打地鼠算法吧。

因为本人是初学Python,这个程序也是学了Python后写的第三个程序,所以代码中有啥坑爹的地方请不要当面戳穿,重点是思路,嗯,如果思路中有啥坑爹的的地方也请不要当面戳穿,你看IE都有脸设置自己为默认浏览器,我写篇渣文得瑟得瑟也是可以接受的对吧……

我用的是Python 2.7,据说Python 2和Python 3差别挺大的,比我还菜的小伙伴请注意。

0x01 思路整理

懒得文字叙述了,画了张草图,大家应该可以看懂。

首先老规矩,先引入一坨不知道有啥用但又不能没有的库:

import re

import urllib

import urllib2

import cookielib

然后顺便声明一些其它变量,以后需要用到:

reload(sys)

sys.setdefaultencoding('utf-8') #将字符编码置为utf-8

luckyList=[] #红包列表

lowest=10 #能忍受红包领奖记录最低为多少

这里用到了一个rsa库,Python默认是不自带的,需要安装一下:https://pypi.python.org/pypi/rsa/

下载下来后运行setpy.py install安装,然后就可以开始我们的开发步骤了。

0x02 微博登陆

抢红包的动作一定要登陆后才可以进行的,所以一定要有登录的功能,登录不是关键,关键是cookie的保存,这里需要cookielib的配合。

cj = cookielib.CookieJar()
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))
urllib2.install_opener(opener)

这样凡是使用opener进行的网络操作都会对处理cookie的状态,虽然我也不太懂但是感觉好神奇的样子。

接下来需要封装两个模块,一个是获取数据模块,用来单纯地GET数据,另一个用来POST数据,其实只是多了几个参数,完全可以合并成一个函数,但是我又懒又笨,不想也不会改代码。

def getData(url) :
        try:
                req  = urllib2.Request(url)
                result = opener.open(req)
                text = result.read()
                text=text.decode("utf-8").encode("gbk",'ignore')
                return text
        except Exception, e:
                print u'请求异常,url:'+url
                print e
 
def postData(url,data,header) :
        try:
                data = urllib.urlencode(data)  
                req  = urllib2.Request(url,data,header)
                result = opener.open(req)
                text = result.read()
                return text
        except Exception, e:
                print u'请求异常,url:'+url

有了这两个模块我们就可以GET和POST数据了,其中getData中之所以decode然后又encode啥啥的,是因为在Win7下我调试输出的时候总乱码,所以加了些编码处理,这些都不是重点,下面的login函数才是微博登陆的核心。

(代码较多,回复“红包”查看)

这里面的参数啊加密算法啊都是从网上抄的,我也不是很懂,大概就是先请求个时间戳和公钥再rsa加密一下最后处理处理提交到新浪登陆接口,从新浪登录成功之后会返回一个微博的地址,需要请求一下,才能让登录状态彻底生效,登录成功后,后面的请求就会带上当前用户的cookie。

0x03 指定红包抽取

成功登录微博后,我已迫不及待地想找个红包先试一下子,当然首先是要在浏览器里试的。点啊点啊点啊点的,终于找到了一个带抢红包按钮的页面了,F12召唤出调试器,看看数据包是咋请求的。

可以看到请求的地址是http://huodong.weibo.com/aj_hongbao/getlucky,主要参数有两个,一个是ouid,就是红包id,在URL中可以看到,另一个share参数决定是否分享到微博,还有个_t不知道是干啥用的。

好,现在理论上向这个url提交者三个参数,就可以完成一次红包的抽取,但是,当你真正提交参数的时候,就会发现服务器会很神奇地给你返回这么个串:

{"code":303403,"msg":"抱歉,你没有权限访问此页面","data":[]}

这个时候不要惊慌,根据我多年Web开发经验,对方的程序员应该是判断referer了,很简单,把请求过去的header全给抄过去。

(代码较多,回复“红包”查看)

这样的话理论上就没啥问题了,事实上其实也没啥问题。抽奖动作完成后我们是需要判断状态的,返回的res是一个json串,其中code为100000时为成功,为90114时是今天抽奖达到上限,其他值同样是失败,所以:

hbRes=json.loads(res)
if hbRes["code"]=='901114': #今天红包已经抢完
        print u"---------已达上限---------"
        print  "----------......----------"
        log('lucky',str(id)+'---'+str(hbRes["code"])+'---'+hbRes["data"]["title"])
        exit(0)
elif hbRes["code"]=='100000':#成功
        print u"---------恭喜发财---------"
        print  "----------......----------"
        log('success',str(id)+'---'+res)
        exit(0)
 
if hbRes["data"] and hbRes["data"]["title"]:
        print hbRes["data"]["title"]
        print  "----------......----------"
        log('lucky',str(id)+'---'+str(hbRes["code"])+'---'+hbRes["data"]["title"])
else:
        print u"---------请求错误---------"
        print  "----------......----------"
        log('lucky',str(id)+'---'+res)

其中log也是我自定义的一个函数,用来记录日志用的:

def log(type,text):
        fp = open(type+'.txt','a')
        fp.write(text)
        fp.write('\r\n')
        fp.close()

0x04 爬取红包列表

单个红包领取动作测试成功后,就是我们程序的核心大招模块了——爬取红包列表,爬取红包列表的方法和入口应该有不少,比如各种微博搜索关键字啥啥的,不过我这里用最简单的方法:爬取红包榜单。

在红包活动的首页(http://huodong.weibo.com/hongbao)通过各种点更多,全部可以观察到,虽然列表连接很多,但可以归纳为两类(最有钱红包榜除外):主题和排行榜。

继续召唤F12,分析这两种页面的格式,首先是主题形式的列表,比如:http://huodong.weibo.com/hongbao/special_quyu

可以看到红包的信息都是在一个类名为info_wrap的div中,那么我们只要活动这个页面的源码,然后把infowrap全抓出来,再简单处理下就可以得到这个页面的红包列表了,这里需要用到一些正则。

(代码较多,回复“红包”查看)

话说正则好难,学了好久才写出来这么两句。还有这里的info中append进去了一个info[4],是我想的一个大概判断红包价值的算法,为什么要这么做呢,因为红包很多但是我们只能抽四次啊,在茫茫包海中,我们必须要找到最有价值的红包然后抽丫的,这里有三个数据可供参考:现金价值、礼品价值和领取人数,很显然如果现金很少领取人数很多或者奖品价值超高(有的甚至丧心病狂以亿为单位),那么就是不值得去抢的,所以我憋了半天终于憋出来一个衡量红包权重的算法:红包价值=现金/(领取人数+奖品价值)。

排行榜页面原理一样,找到关键的标签,正则匹配出来。

好,现在两中专题页的列表我们都可以顺利爬取了,接下来就是要得到列表的列表,也就是所有这些列表地址的集合,然后挨个去抓。

(代码较多,回复“红包”查看)

0x05 判断红包可用性

这个是比较简单的,首先在源码里搜一下关键字看看有没有抢红包按钮,然后再到领取排行里面看看最高纪录是多少,要是最多的才领那么几块钱的话就再见吧……

其中查看领取记录的地址为http://huodong.weibo.com/aj_hongbao/detailmore?page=1&type=2&_t=0&__rnd=1423744829265&uid=红包id

0x06 收尾工作

主要的模块都已经搞定,现在需要将所有的步骤串联起来:

def start(username,password,low,fromFile):
        gl=False
        lowest=low
        login(username , password)
        if fromfile=='y':
                if os.path.exists('luckyList.txt'):
                        try:
                                f = file('luckyList.txt')
                                newList = []  
                                newList = p.load(f)
                                print u'---------装载列表---------'
                                print  "----------......----------"
                        except Exception, e:
                                print u'解析本地列表失败,抓取在线页面。'
                                print  "----------......----------"
                                gl=True
                else:
                        print u'本地不存在luckyList.txt,抓取在线页面。'
                        print  "----------......----------"
                        gl=True
        if gl==True:
                getList()
                from operator import itemgetter
                newList=sorted(luckyList, key=itemgetter(4),reverse=True)
                f = file('luckyList.txt', 'w')  
                p.dump(newList, f) #把抓到的列表存到文件里,下次就不用再抓了
                f.close() 
 
        for lucky in newList:
                if not 'http://huodong.weibo.com' in lucky[3]: #不是红包
                        continue
                print lucky[3]
                id=re.findall(r'(\w*[0-9]+)\w*',lucky[3])
                getLucky(id[0])

因为每次测试的时候都要重复爬取红包列表,很麻烦,所以加了段将完整列表dump到文件的代码,这样以后就可以读本地列表然后抢红包了,构造完start模块后,写一个入口程序把微博账号传过去就OK了:

if __name__ == "__main__":  
        print u"------------------微博红包助手------------------"
        print  "---------------------v0.0.1---------------------"
        print  u"-------------by @无所不能的魂大人----------------"
        print  "-------------------------------------------------"
 
        try:
                uname=raw_input(u"请输入微博账号: ".decode('utf-8').encode('gbk'))
                pwd=raw_input(u"请输入微博密码: ".decode('utf-8').encode('gbk'))
                low=int(raw_input(u"红包领取最高现金大于n时参与: ".decode('utf-8').encode('gbk')))
                fromfile=raw_input(u"是否使用luckyList.txt中红包列表:(y/n) ".decode('utf-8').encode('gbk'))
        except Exception, e:
                print u"参数错误"
                print  "----------......----------"
                print e
                exit(0)
 
        print u"---------程序开始---------"
        print  "----------......----------"
        start(uname,pwd,low,fromfile)
        print u"---------程序结束---------"
        print  "----------......----------"
        os.system('pause')

0x07 走你!

0x07 总结

基本的爬虫骨架已经基本可以完成了,其实这个爬虫的很多细节上还是有很大发挥空间的,比如改装成支持批量登录的,比如优化下红包价值算法,代码本身应该也有很多地方可以优化的,不过以我的能力估计也就能搞到这了。

最后程序的结果大家都看到了,我写了几百行代码,辛辛苦苦换来的只是一组双色球,尼玛坑爹啊,怎么会是双色球呢!!!(旁白:作者越说越激动,居然哭了起来,周围人纷纷劝说:兄弟,不至于的,不就是个微博红包么,在支付宝手都撸酸了也没咻出个红包。)唉,其实我不是哭这个,我难过的是我已经二十多岁了,还在做写程序抓微博红包这么无聊的事情,这根本不是我想要的人生啊!

原文发布于微信公众号 - 大数据挖掘DT数据分析(datadw)

原文发表时间:2016-02-18

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

扫描关注云+社区