怎么像瓦力酱和隔壁王叔叔那样在豆瓣抢沙发?

  • 时间:
  • 浏览:0
  • 来源:知而不乎

经常上豆瓣的文青不知道有没有看到“瓦力酱”老是抢沙发呢?以前我也觉得很神奇,好像说秒回的,不知道它手这么快,经过慢慢的了解了才知道,瓦力酱原来是一机器人,都不搭理人的,类似的还有“王叔叔”之类的,姑且叫它们“抢沙发程序吧”,这个疑问一直没有答案,但心中早已种下了“要做一个抢沙发机器人”的,但苦于如何实现,没有人指导,百度也没答案。如今,学习了Python,答案慢慢的浮出来了。

瓦力酱 隔壁王叔叔 是怎么做到的?

当然了,我不是瓦力酱,不可能真正知道它是如何实现的,但是基本的方法可以应该差不多的。

1、模拟用户登录
要发表回复肯定是要登录才行,而且要维持登录状态,最好处于同一个Session,这样才不容易被反爬虫的重新屏蔽,这个过程可能会要输入验证码。
2、监控
首先得监控小组的主题列表页面,不管它是监控各个小组的,还是就是监控“小组”那个页面,都是要找到刚刚发布的,0回复的主题。然后就要间隔一定的时间刷新页面,重新获取页面中0回复的主题。
3、发表回复
经过监控主题列表,找到了0回复的主题要赶紧回复抢沙发喽,就要模拟用户提交数据,和登录的过程差不多。

4、循环
除了登录意外,整个刷新页面,获取0回复主题,发表回复,这几个步骤说要一直循环自动执行的,不然就不能说是机器人了。

代码实现抢沙发

大致了解整个过程后就是如何来实现啦。经过上一次在《Python入门学习:使用http.cookiejar生产Cookie模拟用户登陆》中写的模拟登录,也测试过了登录豆瓣的,但是由于换了个环境,基本的原理差不多的,不过所有代码要重现敲了。

环境

操作系统:OS X Yosemite(版本 10.10.5 )

Python版本:2.7.10

外部库:BeautifulSoup4、requests

完整代码:https://github.com/zhaoyoucai/robot/blob/master/doubanrobot.py

(一)重写Python实现模拟用户登录

和《Python入门学习:使用http.cookiejar生产Cookie模拟用户登陆》中不一样的是这次使用了requests库,因为在Python 3.4版本中安装BeautifulSoup4一直都搞不定,所有就干脆在Python 2.7来,还有好多好用的库又可以用起来了。

1、创建会话对象

首先还是得构造一个字典数据结构的header用于模拟登录的时候Session使用

  1. headers = {'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
  2. 'Accept-Encoding': 'gzip, deflate, compress',
  3. 'Accept-Language': 'zh-CN,zh;q=0.8',
  4. 'Cache-Control': 'max-age=0',
  5. 'Connection': 'keep-alive',
  6. 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.152 Safari/537.36'}
  7.  
  8. s = requests.Session()
  9. s.headers.update(headers)

这里首先需要了解Session的概念,Session即会话,简单理解就是允许通过将对象存储在 Web服务器的内存中在整个用户会话过程中保持任何对象,当一个session第一次被启用时,一个唯一的标识被存储于本地的cookie中。会话对象让我们能够跨请求保持某些参数,我们需要在同一个Session实例发出的所有请求之间保持cookies。使用requests可以轻松的创建Session对象:requests.Session() [参考:http://cn.python-requests.org/en/latest/user/advanced.html

另外我们可以使用update方法将header数据追加到会话对象的header消息头中,有点类似之前的Opener对象的addheaders。

以上我们就完成一个会话创建与初始化工作,后面的访问请求都是基于这个会话,并保持整个会话的相关参数直到结束。

2、访问首页获取验证码与初始化登录数据

我选择重首页开始访问登录,需要基本的数据,开始可能不需要输入验证码,但是访问多了就需要了,所有这里要请求后把验证码的图片URL打印出来,等待接受输入验证码,手动在浏览器打开图片识别验证码后输入,程序继续执行。这样登录所需的数据就准备齐全了。关于BeautifulSoup的使用,可以参考《Python入门学习:Beautiful Soup 4检查页面TDKH标签》,需要详细的使用文档参考:http://www.crummy.com/software/BeautifulSoup/bs4/doc/

代码片段如下:

  1. r1 = s.get(URL_HOME)
  2. sp = BeautifulSoup(r1.content)
  3. captcha_id = sp.find(attrs={"name": "captcha-id"}).get('value')
  4. captcha_image = sp.find('img','captcha_image').get('src')
  5. print(captcha_image)
  6. captcha_solution = raw_input("输入验证码:\n")
  7. login_data={
  8. 'source':'index_nav',
  9. 'form_email':'g******t@gmail.com',
  10. 'form_password':'********',
  11. 'captcha-solution':captcha_solution,
  12. 'captcha-id':captcha_id,
  13. 'remember':'on'
  14. }

执行中会要求输入验证吗,如下图:

这样登录所需的数据准备好了之后,写在一个字典数据中,完成初始化,已备登录提交使用。

3、提交登录获取主题列表页面

  1. s.post(URL_LOGIN,data=login_data)
  2. r = s.get(URL_GROUP)

非常简单,提交数据使用post方法,访问获取页面数据使用get方法。正常登录成功之后访问的http://www.douban.com/group/会说正常的,未登录成功则是会302重定向至http://www.douban.com/group/explore

(二)监控与循环

成功登录并获取主题列表后就要循环刷新监控这个页面的0回复主题,整个过程循环很简单:

  1. if r.url != URL_GP_EXPlORE:
  2. print('登录成功...\n')
  3. html = r.content
  4. soup = BeautifulSoup(html)
  5. topics = soup.find('div','topics')
  6. topics = topics.find_all('tr','pl',limit=50)
  7. for topic in topics:
  8. subject = topic.find('td','td-subject').a.get('href')
  9. reply = topic.find('td','td-reply').get_text()
  10. sum = re.findall("\d+", reply)
  11. sum = int(sum[0])
  12. if sum < 1:
  13. print('go to reply...')
  14. ......
  15. time.sleep(random.randrange(120,180))
  16. r = s.get(URL_GROUP)
  17. print(time.strftime("%Y-%m-%d %H:%M:%S"))

(注意:代码缩进被打乱了)

代码也不复杂,整个逻辑清楚就好,再次需要使用BeautifulSoup,提取页面的标签元素非常方便,主要提取啦主题的URL、主题的回复数,另外其他的回复时间、小组等暂时不用就不必要获取了,省点时间。另外一个重要的地方是:

  1. sum = re.findall("\d+", reply)

使用了正则表达式来提取“0回复”中的数字部分,好进行处理。判断回复数小于1就是可以抢沙发到主题,提取URL后进行后续的回复操作。

抢完一轮沙发后,暂停一定时间再刷新页面,再使用:

  1. r = s.get(URL_GROUP)

重新获取页面内容即可。

(三)发表回复抢沙发

这个是重点,但是却也很简单,很登录的过程差不多,就是一个提交表单的操作:

  1. if sum < 1:
  2. print('go to reply...')
  3. print(subject)
  4. t = s.get(subject)
  5. s.post(subject+URL_COMMENT,data = randCommnet())

上面提交表单的数据使用了一个随机生成的函数,是因为怕回复内容都一样容易被揪,所以会从一个回复内容列表中随机提取一个来回复,函数代码类似《Python入门学习:应用random函数随机生成HTTP请求headers信息》中随机生成一个header的过程,代码就不贴了,参考全部代码到我的Github账号。

看一下成果吧:

时间虽然不是秒回,但抢沙发才是重点,还好没被怀疑是机器人哈,就这样和瓦力酱跟隔壁王叔叔差不多了。

另外需要注意,如果被反机器人机制识别了,即使登录了,回复还是要输入验证码的,回复不成功没有提示,暂时没去解决,要是以后能写识别图片中等验证码那就好了(好难啊!)

猜你喜欢

Python入门学习:使用http.cookiejar生产Cookie模拟用户登陆

有的网站,特别像社交网站,需要登陆才能抓取到网站的数据,那么光模拟浏览器请求网站内容是还不够了,还需要能够模拟用户登陆网站,然后保留登陆状态,获取网站相关的内容。想要成功模拟真

2018-05-17

Python入门学习:应用random函数随机生成HTTP请求headers信息

为什么抓取会收到限制要采集百度数据,查询关键词排名等,因为短时间内发出太多的请求,会受到百度局域网异常访问屏蔽策略的限制。出现以下错误信息:要突破这样的限制,必须伪装成为真正的

2018-05-17

Python入门学习:模拟浏览器查询百度获取结果

本来学习Python就是想和SEO相关的,所以就在学习的时候把一下常见的需求引进来,这样动力大,学起来就快一些,深刻一些了。SEO最常用的的恐怕就是查询关键词的排名了,手动查询

2018-05-17

Python入门学习:Beautiful Soup 4检查页面TDKH标签

环境:Python3.3.5beautifulsoup4-4.3.2Eclipse+PyDev利用BeautifulSoup4能够很方便的提取页面的标签,那我就来写一个检查页面

2018-05-17

python入门学习:采集搜狗下拉框联想词

最近在拿Python练手,单纯的学习又太枯燥,直接用来实现一些简单功能这样积极性高,效果会好点。环境:Python3.3.5+eclipse+pydev先上代码:#encodi

2018-05-17