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的值每次访问时均会改动。因此,需获得该值方可完成登录。
获取源码后可通过解析网页源码的方法获取。
我最开始的时候用了一种比较笨的方法:

#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')

其实可以用正则表达式:

#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:

#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是有内容的。

#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'))