畢設題目要使用到新浪微博數據,因此要爬取新浪微博的數據。通常而言,新浪微博的爬蟲有兩種模式:新浪官方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來實現跳轉。可是我沒有具體分析。