毕设题目要使用到新浪微博数据,因此要爬取新浪微博的数据。通常而言,新浪微博的爬虫有两种模式:新浪官方API和模拟登陆新浪微博。两种方法的异同点和适用状况就无须赘述了。前辈的文章已经很是多了。写这篇文章主要记录本身的探究过程。javascript
参考文章:1,解析新浪微博的登陆过程php
2,[Javascript] 爬虫 模拟新浪微博登录html
3,用java程序模拟登录新浪微博java
背景知识:Http协议,HttpClient开源包。ajax
1,微博登录流程算法
使用Firefox下的HttpFox或者Chrome下的[工具]->[开发者工具](F12快捷键启动)能够查看浏览器与网站服务器之间的报文交换信息。浏览器
我使用的是FireFox下面的HttpFox。建议提早删除FireFox以前保存的关于新浪微博的Cookies。这样登陆过程更明显。服务器
首先在地址栏中输入weibo.com网址,进入到登录界面。而后开启HttpFox,输入帐号(account)和密码(password),单击登陆按键,正常登录。cookie
如上图四个高亮项所示,微博的登陆过程主要为四步HTTP请求:工具
(1)GET http://login.sina.com.cn/sso/prelogin.php
(2)POST http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.11)
(3)GET http://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack&sudaref=weibo.com
(4)GET http://weibo.com/u/5081950920/home?wvr=5&uut=fin&from=reg
下面对四步进行解析:
(1)GET http://login.sina.com.cn/sso/prelogin.php
此步骤是向服务器请求servertime,nonce等参数。此时可暂不了解这些参数的用处。
首先GET请求的参数为:
这里,‘su’参数是登陆帐户account通过BASE64加密事后获得的字符串,先将account中的‘@’替换为'%40',而后对其BASE64加密,获得su的值。‘_’参数的值是当前时间(毫秒值)。其他参数值通常不变。
样例:
http://login.sina.com.cn/sso/prelogin.php?entry=weibo&callback=sinaSSOController.preloginCallBack&su=Y29tbWVudHN3ZWlibyU0MDE2My5jb20%3D&rsakt=mod&checkpin=1&client=ssologin.js(v1.4.11)&_=1395726032529
向服务器发送这个请求后,会获得服务器的JSon格式的返回值:
sinaSSOController.preloginCallBack({"retcode":0,"servertime":1395726033,"pcid":"gz-3271d864f76816bbfbd651c6887ba9eabf59","nonce":"04DGHY","pubkey":"EB2A38568661887FA180BDDB5CABD5F21C7BFD59C090CB2D245A87AC253062882729293E5506350508E7F9AA3BB77F4333231490F915F6D63C55FE2F08A49B353F444AD3993CACC02DB784ABBB8E42A9B1BBFFFB38BE18D78E87A0E41B9B8F73A928EE0CCEE1F6739884B9777E4FE9E88A1BBE495927AC4A799B3181D6442443","rsakv":"1330428213","showpin":0,"exectime":157})
retcode为0表示执行成功;servertime,nonce是后期对用户密码password加密用的参数。pubkey是加密用的公钥,它的值通常为固定不变的,任何一次请求返回值都同样。raskv也是加密使用的参数。其他参数用处不大。
(2)POST http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.11)
这一步就是向服务器提交表单,表单参数为:
Parameter | Value | 说明 |
entry | 固定值 | |
gateway | 1 | 固定值 |
from | 空值 | |
savestate | 7 | 固定值 |
useticket | 1 | 固定值 |
pagerefer | 空值 | |
vsnf | 1 | 固定值 |
su | Y29tbWVudHN3ZWlibyU0MDE2My5jb20= | 帐号account通过BASE64加密后获得的值 |
service | miniblog | 固定值 |
servertime | 1395726063 | 上一步获取的值 |
nonce | 04DGHY | 上一步获取的值 |
pwencode | rsa2 | 新浪所使用的加密方法,具体值与新浪使用算法有关。短时间内应该为固定值 |
rsakv | 1330428213 | 上一步获取的值 |
sp | 一个256位的密文 |
密码password加密后的值,具体加密方法下面详细介绍 |
encoding | UTF-8 | 固定值 |
prelt | 171 | 一个在[100, 1000]内取随机值 |
url | http://weibo.com/ajaxlogin.php?framelogin=1&callback=parent.sinaSSOController.feedBackUrlCallBack | 固定值 |
returntype | META | 固定值 |
将该表单提交到URL:
http://login.sina.com.cn/sso/login.php?client=ssologin.js(v1.4.11)
这个URL版本不断变化,如今为版本1.4.11。本身开发代码时,能够注意一下当时的具体版本。
上述参数pagerefer有时候会改成
ssosimplelogin | 1 | 固定值 |
该脚本文件中包含了整个登录过程,同时包含了 RSA加密算法,WSSE加密算法和BASE64加密算法。目前该脚本文件的版本为 1.4.11 ,版本一直在升级,升级过程加密算法可能会作更改。具体加密过程此处不表,课查看js该文件,或者翻阅文章开头的连接博文,里面讲解比较详细。
具体而言,就是RSA加密算法是将servertime,nonce与帐户密码连接,同时设置rsaPubkey和‘10001’(固定值)做为参数,进行RSA加密,如今执行的是这一版本。
RSA: request["servertime"] = me.servertime; request["nonce"] = me.nonce; request["pwencode"] = "rsa2"; equest["rsakv"] = me.rsakv; var RSAKey = new sinaSSOEncoder.RSAKey(); RSAKey.setPublic(me.rsaPubkey, '10001'); password = RSAKey.encrypt([me.servertime, me.nonce].join("\t") + "\n" + password);
WSSE加密算法曾经做为sp的加密算法,如今不采用,之后或许也会从新采用。具体行为就是两次SHA1加密password,而后加入servertime和nonce再SHA1加密一次。
WSSE: request["servertime"] = me.servertime; request["nonce"] = me.nonce; request["pwencode"] = "wsse"; password=sinaSSOEncoder.hex_sha1(""sinaSSOEncoder.hex_sha1(sinaSSOEncoder.hex_sha1(password)) + me.servertime + me.nonce);
而后表单提交以后,会获得一个html文件(在HttpFox中查看Content内容)。
<html> <head> <title>ÐÂÀËͨÐÐÖ¤</title> <meta http-equiv="refresh" content="0; url='http://weibo.com/sso/login.php?url=http%3A%2F%2Fweibo.com%2Fajaxlogin.php%3Fframelogin%3D1%26callback%3Dparent.sinaSSOController.feedBackUrlCallBack%26sudaref%3Dweibo.com&ticket=ST-NTA4MTk1MDkyMA==-1395726048-gz-E9A629068822EF01DD1427CA6D0C14D9&retcode=0'"/> <meta http-equiv="Content-Type" content="text/html; charset=GBK" /> </head> <body bgcolor="#ffffff" text="#000000" link="#0000cc" vlink="#551a8b" alink="#ff0000"> <script type="text/javascript" language="javascript"> location.replace("http://weibo.com/sso/login.php?url=http%3A%2F%2Fweibo.com%2Fajaxlogin.php%3Fframelogin%3D1%26callback%3Dparent.sinaSSOController.feedBackUrlCallBack%26sudaref%3Dweibo.com&ticket=ST-NTA4MTk1MDkyMA==-1395726048-gz-E9A629068822EF01DD1427CA6D0C14D9&retcode=0"); </script> </body> </html>
重点在于
<script type="text/javascript" language="javascript"> location.replace("http://weibo.com/sso/login.php?url=http%3A%2F%2Fweibo.com%2Fajaxlogin.php%3Fframelogin%3D1%26callback%3Dparent.sinaSSOController.feedBackUrlCallBack%26sudaref%3Dweibo.com&ticket=ST-NTA4MTk1MDkyMA==-1395726048-gz-E9A629068822EF01DD1427CA6D0C14D9&retcode=0"); </script>
在location.replace中会有个URL地址。咱们要抽取出这个URL。
注意:若是rectcode不为0,则表示到此为止一切步骤都正常执行。若是返回其余值,则表示执行错误,没法向下继续执行。
(3)这步在HttpFox中表现为Redirect to第二步抽取的URL,因此咱们在Coding时,直接请求这个网址便可得到微博登录权限。
(4)这步是作个示范,微博登陆成功之后,便可访问新浪微博的URL了。
上述过程若是是用Java实现,使用HttpClient来访问URL,必定要注意,Login时,从头至尾只能使用一个HttpClient,由于HttpClient会保存一系列的cookie,若是new一个新的HttpClient,这些保存所有没有,访问没法进行。
第三四部,会涉及一系列的Cookies,可使用Cookies来实现跳转。可是我没有具体分析。