SKYue

Python爬虫:模拟登录知乎

接上一篇《Python 爬虫:抓取知乎某一话题下的全部问题》,需要说明的是我换了开发环境及一些工具库,现在用的是

环境:Python 3.5
HTTP请求:request
XML处理:BeautifulSoup + lxml

能够抓取一个话题下的问题后,我在想要如何抓取知乎全站数据呢?传统的方法,随便从某一个页面(通常是首页)开始抓取,然后提取页面中的URL,再根据提取到的URL去抓下一个页面。但对于新手,感觉一开始就这样处理,难度挺大,比如要做很多URL的分析、调度、去重等。又不想直接上Scrapy这样的框架,那就得想想其他法子。

考虑到我只是抓取知乎,而且知乎网站的结构比较清晰。内容上是按照「话题→问题→答案→回复」组织的,所以完全可以按照这个顺序去抓,最后再抓取「用户」信息就大功告成了。

那第一步就是要抓所有话题,找到话题结构页,从「根话题」开始,结果发现话题结构页需要登录才能查看。于是乎有了这篇文章。

获取登录信息

使用chrome的开发者工具查看知乎的登录信息,如下图:

短乎登录页

可以看到知乎的登录地址是http://www.zhihu.com/login/email,请求方式是POST,登录时需要提交五个数据,分别是

_xsrf: 估计是随机生成的校验类数据,可在网页源码中找到
password: 密码
captcha: 验证码
remember_me: 记住我,布尔值
email: 邮箱地址

email、password和remember_me这三个很简单,主要是如何拿到_xsrf和验证码。

在网页原码中可以找到下面这段代码,就是_xsrf,可以使用BeautifulSoup解析HTML获取。

<input type="hidden" name="_xsrf" value="df557baede680642b1e1ab5974011246"/>

验证码是图片,复制图片链接地址就能看到,如下:

http://www.zhihu.com/captcha.gif

程序中需要抓取验证码图片并手动输入验证码才行。

模拟登录知乎

搞清楚登录过程及信息后,就可以开始写代码了。

import requests
import re
from bs4 import BeautifulSoup

# 设置一个session对象,保存登录信息
s = requests.Session()

# 设置headers
headers = {
    "Accept": "*/*",
    "Accept-Encoding": "gzip,deflate",
    "Accept-Language": "en-US,en;q=0.8,zh-TW;q=0.6,zh;q=0.4",
    "Connection": "keep-alive",
    "Content-Type":" application/x-www-form-urlencoded; charset=UTF-8",
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36",
    "Referer": "http://www.zhihu.com/"
}

html = s.get('http://www.zhihu.com/', headers=headers)  # GET请求,获取一个响应对象
soup = BeautifulSoup(html.text,'lxml-xml')  # 使用BeautifulSoup解析HTML

# 获取_xsrf
_xsrf = soup.findAll(type='hidden')[0]['value']

# 获取验证码图片并保存在本地
captcha_url = 'http://www.zhihu.com/captcha.gif'
captcha = s.get(captcha_url, stream=True, headers=headers)
with open('captcha.gif', 'wb') as f:
    for line in captcha.iter_content(10):
        f.write(line)
    f.close()

# 输入获取到的验证码,并入变量captch_str
print('输入验证码:', end='')
captcha_str = input()

# POST请求需要提交的信息组合
data = {
    '_xsrf': _xsrf,
    'email': '123456789@qq.com',  # 请用正确的邮箱
    'password': 'password',  # 请用正确的密码
    'remember_me': True,
    'captcha': captcha_str
}

# 登录请求
r = s.post(url='http://www.zhihu.com/login/email', data=data, headers=headers)

# 验证登录是否成功
print('登录状态:', r.json())

使用正确的邮箱和密码后,运行程序,将提示输入验证码,根据本地保存的图片输入即可。最终的输出如下(发现「陆」字错了):

输入验证码hrfv
登录状态 {'r': 0, 'msg': '登陆成功'}

大功告成。

NEXT:抓取知乎的话题结构

Code

共有7篇文章

Diary

共有51篇文章

Poetry

共有2篇文章

Movie

共有22篇文章

Read

共有9篇文章

Repost

共有4篇文章

Review

共有11篇文章

Tech

共有28篇文章

Trade

共有25篇文章

Travel

共有8篇文章

2019

共有3篇文章

2018

共有34篇文章

2017

共有23篇文章

2016

共有89篇文章

2015

共有18篇文章