python通过Requests登录知乎

相关资料

python标准库中的urllib2提供了大多HTTP功能,但使用较为麻烦。关于使用该库实现登录知乎的方法可参考链接->使用Python模拟登陆知乎和v2ex
Requests较urllib更为方便,使用前需要安装。相关资料可参考链接->Requests文档

通过post将帐号、密码及一些cookie等相关信息发送至指定链接即可完成登录

需要post的内容

post中需要包含的的具体内容可通过chrome获得:
在浏览器地址栏输入http://www.zhihu.com/#signin->F12->Network->勾选Preserve log->点击登录后查看浏览器发送的数据包(点击登录后会刷出一堆包,直接拖到最上面找浏览器发的登陆数据包信息)。
根据登录的方式不同(邮箱/手机号),发送的包名也不同,分别为email/phone_num
post中包含四个字段:_xsrf,password,remember_me,phone_num,同样的,最后一个字段名根据登录方式不同而改变,为phone_num或email。这里以phone_num登录为例

获取post需要的内容

四个字段中password,remember_me,phone_num很好理解,这里不做解释。
_xsrf是一个隐藏字段,当登录知乎主页(https://www.zhihu.com/)时,查看网页源代码可看到其中有这么一个标签:,其中value的值每次访问时均会改动。因此,需获得该值方可完成登录。
获取源码后可通过解析网页源码的方法获取。
我最开始的时候用了一种比较笨的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#encoding=utf8
from HTMLParser import HTMLParser
import requests
import sys

class MyHTMLParser(HTMLParser):
def __init__(self,des_name):
HTMLParser.__init__(self)
self.result='a'
self.desName=des_name;

def handle_starttag(self, tag, attrs):
if tag == 'input':
for attr in attrs:
if cmp(('name',self.desName),attr) == 0:
for temp in attrs:
if temp[0] == 'value':
self.result = temp[1]
def getDesData(htmlContent,desName):
parser = MyHTMLParser(desName)
parser.feed(htmlContent)
return parser.result
if __name__ == "__main__":
s = requests.session()
r = s.get('http://www.zhihu.com/')
html_Content = r.text
print getDesData(html_Content,'_xsrf')

其实可以用正则表达式:

1
2
3
4
5
6
7
8
9
10
11
12
13
#encoding=utf8
import requests
import re
import sys

def getXSRF(r):
cer = re.compile('name=\"_xsrf\" value=\"(.*)\"', flags = 0)
strlist = cer.findall(r.text)
return strlist[0]
if __name__ == "__main__":
s = requests.session()
r = s.get('http://www.zhihu.com/')
print getXSRF(r)

最后发现Requests里面可以直接解析cookies:

1
2
3
4
5
6
7
8
9
#encoding=utf-8
from HTMLParser import HTMLParser
import requests

if __name__ == "__main__":
s = requests.session()
r = s.get(mainURL'http://www.zhihu.com/')
print r.cookies
print r.cookies['_xsrf']

获取到_xsrf后就可以通过post登录啦~
这里需要注意:
获取_xsrf的页面应该是-http://www.zhihu.com/
post的目标页面应该是-http://www.zhihu.com/login/phone_num

完整的登录源码

这里我用的登录方式为手机号,将phonenum和pwd修改成自己的帐号密码就行了。
采用邮箱登录需要对loginURL以及login_data做相应修改。登录完成后可以get主页测试下,登录成功后创建的zhihu_test.html是有内容的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#encoding=utf-8
from HTMLParser import HTMLParser
import requests

if __name__ == "__main__":
phonenum='xxxxxxxxxxx'
pwd='xxxxxxx'
mainURL='http://www.zhihu.com/'
loginURL='http://www.zhihu.com/login/phone_num'

headers = {'User-Agent' : 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.72 Safari/537.36'}

s = requests.session()
r = s.get(mainURL)
print r.cookies #打印页面cookies,可在终端自己查看

login_data = {'_xsrf':r.cookies['_xsrf'], 'phone_num':phonenum, 'password':pwd, 'rememberme':'y'}
t = s.post(loginURL, login_data, headers)
print t.text #显示登录结果,正常情况下应该是{"r:"0,"msg":"\u767b\u9646\u6210\u529f"},"msg"字段中显示的是登录结果(Unicode)

t = s.get(mainURL,verify=False)
print t.text.encode('utf-8')

f = open('zhihu_test.html','w')
f.write(t.text.encode('utf-8'))

本文首发于http://www.miaoyunze.com/,转载请注明出处