畢設題目要使用到新浪微博數據,所以要爬取新浪微博的數據。一般而言,新浪微博的爬蟲有兩種模式:新浪官方API和模擬登錄新浪微博。兩種方法的異同點和適用情況就無須贅述了。前輩的文章已經非常多了。寫這篇文章主要記錄自己的探究過程。
參考文章:1,解析新浪微博的登錄過程
背景知識:Http協議,HttpClient開源包。
1,微博登陸流程
使用Firefox下的HttpFox或者Chrome下的[工具]->[開發者工具](F12快捷鍵啟動)可以查看瀏覽器與網站服務器之間的報文交換信息。
我使用的是FireFox下面的HttpFox。建議提前刪除FireFox之前保存的關於新浪微博的Cookies。這樣登錄過程更明顯。
首先在地址欄中輸入weibo.com網址,進入到登陸界面。然后開啟HttpFox,輸入賬號(account)和密碼(password),單擊登錄按鍵,正常登陸。

如上圖四個高亮項所示,微博的登錄過程主要為四步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來實現跳轉。但是我沒有具體分析。
