学习爬取知乎
很久没有做过Python项目了,最近寒假在家学了一下Python爬虫。
用Python爬知乎已经有很多前辈做过,我在实践中也是借鉴了前辈们的思路。下面说一下我是怎么做的。
需要的基本库
首先说一下项目中用到的库。
1. requests
和urllib
:http基本框架,用来处理http请求,下载和解析部分需要自己另行处理,特点是比较灵活,我用了requests.session来处理大部分http请求(因为它在一个session中保持cookie,而且线程安全并可以Unicode解码);
2. lxml
:用于页面解析,搭配XPath(或者re模块)使用;
3. PIL
和matplotlib
:用于验证码的处理和识别;
4. time
:用于登录时POST数据的处理。
登陆知乎
首先就是要知道知乎登录时会向服务器发出什么数据。在chrome中测试发现登陆需要的信息由有:邮件名(或者电话号)
,验证码
,附加信息(_xsrf)
构成,其中,由于验证码分为输入四位验证码
和点击图像中倒立文字
两种方式,验证码(captcha)
信息也就有两种模式,稍后具体介绍。
下面主要介绍这些信息如何get
和post
:
- get _xsrf: _xsrf信息可以在知乎首页的代码中得到,同时可以得到验证码图片的类型
captcha_lang
。
用lxml
配合xpath
解析这些信息:
headers = {
"Host": "www.zhihu.com",
"Referer": "https://www.zhihu.com/",
'User-Agent':'Mozilla/5.0 (Windows NT 5.1; rv:33.0) Gecko/20100101 Firefox/33.0'
}
login_url = 'https://www.zhihu.com'
element = session.get(login_url, headers=headers)
dom = etree.HTML(element.content.decode('utf-8'))#
_xsrf = dom.xpath('//input/@value')[0]
captcha_lang = dom.xpath('/html/body/div[1]/div/div[2]/div[2]/form/div[1]/div[3]/@data-type')
- get captcha.gif(验证码图片):
通过查询源码,发现验证码图片的URL为https://www.zhihu.com/captcha.gif?r=1484270160013&type=login
,点击倒立文字型的验证码后面需添加'&lang=cn'
这里r=1484270160013
是Unix时间戳[1]
t = str(int(time.time() * 1000))
captcha_url = 'http://www.zhihu.com/captcha.gif?r=' + t + '&type=login'#对应输入四位字母的验证码
captcha_cn_url = 'http://www.zhihu.com/captcha.gif?r=' + t + '&type=login&lang=cn'#对应点击倒立文字的验证码
request.urlretrieve(captcha_url,'E:\myProgram\spider\captcha.gif')#将验证码图片保存到本地
接下来重点就是完成验证码图片的处理了:
- 四位英文验证码:对于四位英文字母的验证码,目前可以直接打开图片然后手动输入验证码。接下来会研究下如何自动识别图片中的验证码。
- 倒立文字:搜了一些博客发现没有这方面的内容,只能自己动手去想办法了,还好最终弄出来了,下面说一下过程:
倒立文字的处理方法
首先,发现POST到服务器上的数据是这个样子的:
查了一下验证码图片的大小是[400*88],也就是说操作过程中把验证码图片的长和宽压缩到一半了;
在点击验证码的时候,查看网页源码发现会出现这样的代码:
对比POST上去的数据发现横纵坐标均比源码上的多8个像素点。应该是考虑到了点击时产生的小圆点(直径16像素点)的大小。这样的话,验证码图片在坐标系中应该是这样显示的:
弄明白原理之后的事情就好说了,直接用matplotlib
库的ginput(self, n=1, timeout=30, show_clicks=True, mouse_add=1, mouse_pop=3, mouse_stop=2)
方法,点击图片中的倒立文字,得到的点击处的像素值,再按照上面的原理计算,即可得到POST的值。
运行程序,得到的msg
信息通过Unicode转码意思是登录成功
最后把cookie保存一下,以备不时之需
项目代码:知乎登录脚本