上一篇文章小试牛刀:使用Python模拟登陆知乎介绍了如何模拟知乎登陆,虽然用到了验证码信息,但请求的参数都是原封不动的传递,刚开始接触的时候,以为难度适中,回头再看的时候,反而感受挺容易的。在这篇文章,将继续介绍模拟登陆。与以前不同的是,此次选择的对象是新浪微博,难度稍微提高了点,好在以往的许多码友们都留有许多经验贴,通过几番斟酌,微博的模拟登陆算是实现了。这两天还在研究如何高性能地爬取微博数据,业余之际乘着还有点记忆,索性将先前的小实验加工成文,算是一份小结吧。下面来看看整个实验过程。php
一如既往,笔者使用的仍是以前的工具,以下:html
新浪微博的登陆有多个URL连接,笔者在实验的时候试了两个,这两个都是新浪通行证登陆页面,都是不须要验证码的。一个是 【http://login.sina.com.cn】,另外一个是 【https://login.sina.com.cn/signup/signin.php?entry=sso】。两个URL虽然很大部分相同,登陆过程当中仅仅是传递参数不同。第一个URL传递的过程对“password”进行了加密,而第二个没有加密,因此若是使用第二个URL进行模拟登陆,就简单多了。在这里,笔者决定选择使用第一种方式进行分析,下面来看详细过程。python
请求登陆过程可概括为三部分git
在模拟登陆以前,先观察浏览器登陆过程当中Fiddler抓到的包,在/sso/login.php
打开以前会先使用“GET”方式请求“/sso/prelogin.php”,请求的URL为:【https://login.sina.com.cn/sso/prelogin.php?entry=account&callback=sinaSSOController.preloginCallBack&su=bGl1ZGl3ZWkxOCU0MHNpbmEuY29t&rsakt=mod&client=ssologin.js(v1.4.15)
】,能够看看下面这张图:github
在Fiddler中,能够点击“Preview”查看具体详情,也能够直接将Request URL复制到浏览器上查看,效果图以下:算法
能够看出,这是一个json数据,而且携带了几个参数,咱们关心的有如下四个:json
说明一下,之因此认为这几个参数比较重要,那是由于后面对“password”的加密须要用到,对其余参数没有说起的缘由是在提交POST时其它的参数并无用到。好了,为了进行进一步探索,咱们从Fiddler的结果能够看出,接下来到了“/sso/login.php”。浏览器
从这里开始,就进行“login.php”页面的请求分析了(详细的Request URL:【https://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.15)
】,后面的时间戳可省略)。点击查看详情,结果图以下:cookie
能够发现/sso/login.php
页面有以下参数(From Data):session
cdult: 3 domain: sina.com.cn encoding: UTF-8 entry: account from: gateway: 1 nonce: AFE3O9 pagerefer: http://login.sina.com.cn/sso/logout.php prelt: 41 pwencode: rsa2 returntype: TEXT rsakv: 1330428213 savestate: 30 servertime: 1478568922 service: sso sp: password sr: 1366*768 su: username useticket: 0 vsnf: 1
到了这里,咱们大概能够知道咱们须要哪些参数了。在From Data 参数列表中,须要咱们指定的参数有下面几个:
对于参数“nonce”、“servertime”、“rsakv”,均可以从第一步中的“prelogin.php” 中直接获取,而“sp”和“su”则是通过加密后的字符串值,至于具体的加密规则,咱们下面经过查看源码分析得出。
首先看看请求“/sso/prelogin.php”的具体状况,看到“client”为“ssologin.js”,见下图:
而后咱们到登陆页面https://login.sina.com.cn中查看源码【view-source:https://login.sina.com.cn/】并搜索“ssllogin.js”,接着点击进入ssologin.js文件,这时咱们可在文件中搜索“username”字符串,找到与“username”相应的加密部分(需仔细查看+揣测),接着搜索“password”,找到“password”的加密部分,最后分析出“username”和“password”的加密规则。加密部分的代码以下图:
加密用户名的代码:
1 |
request.su = sinaSSOEncoder.base64.encode(urlencode(username)); |
加密密码的代码:
1 |
if ((me.loginType & rsa) && me.servertime && sinaSSOEncoder && sinaSSOEncoder.RSAKey) { |
微博对于“username”的加密规则比较单一,使用的是“Base64”加密算法,而对“password”的加密规则比较复杂,虽然使用的是“RSA2”(python中须要使用pip install rsa
安装rsa模块),但加密的逻辑比较多。根据上面的代码,能够看出“password”加密是这样的一个过程:首先建立一个“rsa”公钥,公钥的两个参数都是固定值,第一个参数是登陆过程当中“prelogin.php”中的“pubkey”,第二个参数是加密的“js”文件中指定的“10001”(这两个值须要先从16进制转换成10进制,把“10001”转成十进制为“65537”)。最后再加入“servertime”和“nonce”进行进一步加密。
通过上面的分析以后,发起“POST”请求时的“post_data”基本上已经所有能够获得了,接下来就跟模拟登陆其它网站相似了,可使用“request”,也可使用“urllib2”。下面来看详细代码部分。
Github源码连接:https://github.com/csuldw/WSpider/tree/master/SinaLogin,源码包括下列文件:
为了方便扩展,笔者将代码进行了封装,因此看起来代码量比较多,不过我的以为可读性仍是比较良好,算是凑合吧。
1 |
# -*- coding: utf-8 -*- |
1 |
# -*- coding: utf-8 -*- |
1 |
# -*- coding: utf-8 -*- |