上一篇文章小試牛刀:使用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 -*- |