在以往的文章中,我们主要使用了requests的get方法来直接获取网页的内容。支持GET方法的网页,接受我们的URL, 从URL里面取出参数,然后再将结果返回给浏览器。由于URL的长度是有限制的,所以只能接收少量的参数。而支持POST方法的网页,可以传递大量的参数和大量的信息。如果一个网页只支持POST方法,那这个网页是没有办法在浏览器里面直接输入网址访问的。requests的post方法支持将参数以POST方式提交给网页,并得到网页的返回信息。
大多数的网站,登录的用户名和密码都是通过POST方式提交给服务器的,因此如果可以模拟网站的这个提交行为,就可以模拟登录网站。
我们首先进入知乎的登录页面,打开Chrome的开发者工具的Network选项卡,勾选“Preserve log”并故意输入错误的账号和密码尝试登录,从Chrome抓取到的数据中我们可以找到我们需要的信息:
从以上两张图中,我们可以看到,当我们点击了登录按钮以后,程序会将图二红框中的Form Data下面四个数据使用POST方式发送给图一红框中的https://www.zhihu.com/login/email 这个URL。
注意:如果你输入的账号不是手机号,而是邮箱,数据将会发送到的URL为:https://www.zhihu.com/login/phone_num
上图中的Form Data,后三项的意义显而易见,email: 邮箱, password: 密码, remember_me: 记住我。但是第一项”_xsrf”是什么意思?它后面的一长串数据是哪里来的?
这个时候大家打开登录页面的源代码,你将会找到这样内容:
那么事情就简单了,使用正则表达式或者XPath先从源代码里面把这个xsrf提取出来,然后再和登录信息一起提交即可。
还有一点需要注意:在Form Data中,remember_me后面的值是true, 首字母是小写的。但是在Python里面的布尔值True, 首字母需要大写。
在一般情况下是不需要使用验证码登录的,所以只需要提供图二列出的信息,将它们写成一个字典并POST提交就能实现登录。那么如果遇到验证码怎么办呢?后面我们会有专门的课程将验证码的处理。
现在,我们已经知道了登录知乎的原理,于是就可以通过代码来实现登录。核心代码如下:
data = {'_xsrf': xsrf, 'email': '邮箱', 'password': '密码', 'remember_me': True} session = requests.Session() result = session.post('https://www.zhihu.com/login/email', headers=header, data=data) #这里的result是一个json格式的字符串,里面包含了登录结果 #之后访问知乎的其他页面,只需要使用session.get('网址', headers=header)这种格式 front_page = session.get('https://www.zhihu.com', headers=header) print(front_page.content.decode())
其运行效果如下图所示:
网址返回的登录结果是登录成功,并且查看源代码可以证明是登录成功。
对于其他的网站,整个流程是完全一样的,只是POST提交的参数各有不同。有些网址只需要POST提交用户名和密码就可以了,而另外一些网址,可能还需要从源代码里面提取更多的参数。
#encoding=utf-8 import requests,re,json header={ 'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Encoding':'gzip, deflate, br', 'Accept-Language':'zh-CN,zh;q=0.8', 'Connection':'keep-alive', 'Cookie':'d_c0="ACCAy9ov2AqPTgAkDUuZ-jOeEf8VkJ1jWMw=|1479086751"; q_c1=e0f6b8a4ef414520a96569286788849c|1479086751000|1479086751000; l_cap_id="ODBlM2QzZWJkZDU2NDVmYjk5OGFmMWExZjdlNjE4MTY=|1481529404|b0aa35ca238d60c9b42bc90af950abc75ea7e55f"; cap_id="NTczOGViM2Q2MDAyNDAwYjg0MDI5MGIzYjczM2IwZWM=|1481529404|38baca19c5b6c320d61de3c1a5c57b33622a2bf5"; __utmt=1; r_cap_id="Y2U3ZjRkOTk1MDIwNDNiODgzM2IzNGI2NTZjMzNhNDY=|1481529405|3a5d3af6d915fb0a79cf2dcd925e1cf503cf4ab2"; login="YmVlYzExYThjNWE3NDMzZmEzNzgwMTdhZjc4YTg1M2M=|1481529422|a8210cba1dba488ebfb262877ffd44d9d3e42964"; _xsrf=cf55698c3c4c7b8ae72ee3bc5027c134; __utma=51854390.89943953.1479086837.1481248499.1481529486.8; __utmb=51854390.8.10.1481529486; __utmc=51854390; __utmz=51854390.1481248499.7.7.utmcsr=baidu|utmccn=(organic)|utmcmd=organic; __utmv=51854390.000--|2=registration_date=20151125=1^3=entry_date=20161114=1; _zap=b81df854-46a4-4559-9da4-32dc69f33f7c; n_c=1', 'Host':'www.zhihu.com', 'Upgrade-Insecure-Requests':'1', 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36', } html=requests.get('https://www.zhihu.com/#signin',headers=header).content # print html re_data=re.compile(r'<input type="hidden" name="_xsrf" value="(.*?)"/>') login_token=re.search(re_data,html).group(1) # print login_token data = {'_xsrf': login_token, 'email': 'xxxxxxx', 'password': 'xxxxxxxx', 'remember_me': True} session = requests.Session() result = session.post('https://www.zhihu.com/login/email', headers=header, data=data) #这里的result是一个json格式的字符串,里面包含了登录结果 result_dict=json.loads(result.content) print result_dict #之后访问知乎的其他页面,只需要使用session.get('网址', headers=header)这种格式 front_page = session.get('https://www.zhihu.com', headers=header) print(front_page.content.decode())
此篇博客仅供学习交流
正在敲代码,忽然发现了账号和密码。难道是密码泄漏了???
谢谢张亚楠哥哥提醒,忘了