分类: Java
2013-09-14 13:59:37
原文链接:
概述:
由于业务需要,要编写爬虫代码去爬去新浪微博用户的信息。
虽然在网上能找到不少信息,但由于新浪微博改版,其登陆机制进行了修改,故很多老的文章就不适合用了。
经过一番摸索,成功模拟新浪微博的登陆操作,项目使用的是Javascript语言,在ChromeExtension中运行, 跟大家分享一下这一过程和心得。
注意,本文写于2013.08.16,由于微博业务经常变化,随年月老去,文章可能不再适用。
正文:探索的过程
1. 了解大致过程
登陆微博,使用fiddler工具监视HTTP请求,截获如下操作:
可以看到在微博登陆的整个过程中,有四次重要的HTTP请求,分别是:
(1) GET /sso/prelogin.php
(2) POST /sso/login.php
(3) GET /ajaxlogin.php
(4) GET /u/2813262187
其中,sso是single sign on
(1) 是登陆前的预处理,名字也显而易见--pre,这一步操作主要是拿到了几个重要的参数,用作下一步POST表单的参数。
可以在浏览器中访问这一请求的地址,查看返回的结果:
(v1.4.11)
结果如下:
返回的数据有servertime:服务时间戳,nonce:是一个6位随机码,pubkey:是用于rsa2密码加密的公钥,rsakv:显然也是加密用的。
这四个值都是需要在下一步用到的。
在久版本的新浪微博登陆机制当中,使用的是sha的加密方式,没有pubkey和rsakv参数,
因此,在网上看到的2012年的爬虫代码模拟登陆的代码都已经不适合用,但总体逻辑是没多大变化的,只需要稍作修改还是能用的,我就是这么走过来的,碰壁无数=.=
给出两篇参考文章:
For Python
For PHP
(2) 提交表单的操作,我们依然是查看HTTP请求,看表单内容
看到了,servertime、nonce、rsakv,还有su:加密后的用户名,sp:加密后的密码。现在问题就是用户名跟密码是怎么加密的了,很容易地我们的目光聚焦到js代码上面
请求新浪登陆页面:,里面有用于密码加密的js代码,
里面的代码是加密过的,找个工具解密一下(), 勉强还能看到其中的逻辑的。
(3) 分析ssologin.js
既然我们知道了servertime跟nonce是用于加密的,不妨在文件中搜一下这两个关键字,一搜找到了好东西:
翻回去上文看看,表单中有个su和sp,都在这里了,可以看到su使用的是base64加密方式;而su就稍微复杂一点了,
if中的是新浪当前版本的密码加密方式rsa2的代码,而else中的是就版本sha加密的代码,我们只需要关心if中的内容,
加密过程很简单,先是生成一个RSAKey对象, set PublicKey,然后就加密了。
一项一项地倒推回去,可以知道最后一步加密中最后的一个参数ag是原始的密码值,不会看到眼花的~
概括一下,就是用好长的那一串pubkey和10001作参数调用setPublic() ,注意的是它们都十六进制数;然后用(servertime + nonce + pwd)作参数调用Encrypt()。
我们去看看sinaSSOEncoder是个什么东西,它的定义在解密了的代码的1118行,从这开始截取到文件末尾,挪出来我们自己用,
这就解决了密码加密的问题了。
2. 模拟请求过程
既然知道大致的原理,就可以开始模拟整个登录的过程了,
(1) GET请求 (v1.4.11)
返回的数据中正则匹配到servertime、nonce和rsakv,注意,在请求的时候要把时间戳也一并传到服务器。我们看看fiddler监控到的QueryString:
前五个参数都在URL里面显示声明了,最后的_就自己在发请求的时候补上,传过去吧。
我使用的是Javascript,用Jquery,$.ajax中的data属性里面加进去就好了。
(2) POST请求 (v1.4.11) 提交登录表单
agent是发送请求事务的封装模块,重点看里面的data对象,其中su是base64加密的用户名,每次调用都是固定的,因此写死在这里;
servertime、nonce、rsakv都是在前一步截取的;
sp是加密后的密码,参考上文的加密方式可得。
(代码会在后面分享出来)
(3) 上一步页面请求完成后,返回的数据如下所示
这段代码执行后,页面直接跳转到新的地址上,虽然我们上微博的时候感觉不到有中间页面的跳转,
其中retcode是从服务器返回过来的,为0时才表示正确,能继续访问,如果返回的是其它值,可以看看ssologin.js的源码,里面有各种错误的说明,
本人也在这个地方纠结了很久,之前尝试都是2092(好像是),后来把前面两步的参数传完整(如_),补上Referer,就好了。所以要尽量模拟完整。
第三步就是要截取这个URL,请求之。至此,登录操作完成。
(4) GET请求 ,这是个人主页,能返回个人信息则表示前面的操作成功了,如果是返回登录页,那不好意思,前面的步骤还是再检查一下吧~
参考文章:
老版本新浪,Python
老版本新浪,PHP
新版本新浪,Python http://www.cnblogs.com/mouse-coder/archive/2013/03/03/2941265.html
JQuery Ajax API
ChromeExtension https://developer.chrome.com/extensions/webRequest.html#event-onHeadersReceived
附:代码 http://files.cnblogs.com/sysuys/weiboLogin.rar
说明:
1. 这几个文件是从爬虫项目抽取出来的,所以这些文件跑不起来,但可供参考,代码没有完善,没注释
2. 项目是运行在Chrome插件中的
3. 使用了requirejs.js