前言
有興趣的童鞋,可以立馬抄起python爬網易云音樂的評論了。對于網易云音樂的破解,網上已經有很多現成代碼,你們可以直接拿起就用,但這只會讓你知其然不知其所以然,下一次換一道題目,你同樣不會,還想等著抄答案嗎?因為這個網站的反爬極具代表性,我花了好長的時間才搞清楚其中的原理,現在,我在這里詳細講述爬取思路。
爬取分析
1.首先我們打開網易云音樂隨便一首歌,第一步,先看翻頁邏輯,為什么呢,我發現,比較高端的反爬多半都是AJAX異步為主的,果不然,評論第二頁跟第一頁的地址是一樣的。說的這里,小伙伴可以先去試試。
2.我們先試試能不能拿到數據,比如request的response,或者scrapy的調試模式,你會發現,無論用哪種工具,評論數據都不在網頁里。
3.那么我用selenium的page_source呢,同樣也是不行。
那么數據在哪呢?
現在我們打開瀏覽器的fiddler,刷新抓包一下網頁
我以chrome舉例,你會發現,數據在這個R_SO的XHR里面。
讓我們直接調用這個API接口,返回了空白頁面。那么我們再來分析這個數據是怎么請求的,切到headers頁面,你會發現,這是一個post請求,傳入了兩個參數,一個是params,一個是encSecKey
這兩個參數是什么玩意?怎么來的
先不要急躁,我們先試試,直接傳入這兩個參數,模仿post請求,是否能得到數據呢?
答案是可以的,感覺我們看到曙光了呢,那么我們再來看看,下一頁的params和encSecKey是否有改變。
第一頁與第二頁params對比:
params:lSONbxzJJ8KQQzhI/6QMsCcDhFeUN7vdFJyvHyl0BEi/W2xUi32cLnkoKjOxTam/zz6r4G2Qyqct/nzc9Sx+BCXX4KGINEpLZBxaw3gOB4YFrOl6BDYvt6AVp2TobZ8KPl3lxAxKu196rJYb8eT2cL2hkb++joxlxoP+y5Xkuqh9FOkGl2WFOSQnCnjs22W7EzroZPb3Co/E3l208+W6nmWKNI9qHOxgiStuWa6gR+g=
params:ZJGaP/tOjowd89zzN5554gR30t9/ZYFTTQQclSpmcwN3fpymcuxQU0iEptA2jSl/STYs474HXE0O9TP/gcBo8Y2uAbC6ux/tkmb/PRm0RyWMgihRqZxMspI1S/oOm2ndLKmUNVc+8kq1IyL+jA6jzol1EMjKEBMvr1m25PARvDKAk3CnUOOXe3j+Tk3PEPFXQxtKDkPIkSMPDDbI9iiQvtrhUCmf/iXQFiN+GeyV34w=
第一頁與第二頁encSecKey對比:
encSecKey: 39027236d8ad00f00752c1d3773874e652f02fbc172c218ead51327e19b3feaf72fbf75d6e4f3a475e041db273b3ef6cae23feed1c593ffd5842f53bc626078de0cc3466c33d5b4572c464caa79c1fe5302fd7cfaf105dad044dfa16313a8d6d6c541fb18645894f71519064ba6257f5eea87527eea3169955f5bd7a74e4d6bd
encSecKey: 0970b9e51d4e42213b68d8761fdbb8cee06d198fe5500cd8184774d54a4af11058537c2f1671d2231f6cd6f6cf49dfe8c04367adb037552631ea787b453adf08bfaa10bc314b23e43b2c954072d0b6b2ee6d8b629b4de6d93191ba3c0036f039556736d5fbc63f45bcdc84a3b3ca525c51c3dce2d05a04f461d93d7850b5c017
明顯不一樣,所以我們現在已經明確了問題,如果我們要實現真正的爬取頁面,那么其實就是破解這兩個參數。
JS源頭
這里必須科普一下一個知識,我們之所以能看到五彩紛呈的頁面,并不是遠程服務器加載好再給我們呈現出來的,而是就像正常的下載文件一樣。把服務的js文件下載下來,然后在本地瀏覽器執行。
這里可能會比較難懂一點,我們先點到之前抓包的R_SO文件,如圖操作,找到這個R_SO文件的Initiator
這兩個參數,是由這個core c245e96...的JS文件生成的。
我們,現在直接左鍵點擊打開這個JS文件。(在Chrome里面,當你鼠標移到上面,他會顯示這個Initiator發起的所有文件,我們現在暫時不知道這兩個參數是具體由誰生成的,所以要把所有JS都加載出來)
這是所有的JS,這樣子的JS可讀性很差,所以我們把這一大段JS Ctrl+A,復制,然后再python里創建JS文件,然后粘貼,然后格式化。
格式化按鈕在這
好了,舒服了,接下來,我們再搜索關鍵字,params和encSecKey,很榮幸,我們找到了這兩個關鍵字所在函數。
接下來,你怎么也必須
突然會看JS了吧,你懂我意思吧
JS破解
現在我們拿到了JS的內容,前面的一大段東西都不是事,重點還是我們破解JS的思路。當我們搜索params的時候,會搜出37個matches。
很好,只有三個,你會發現,里面的JS函數是abcd這種難以閱讀的形式,對于我們這種半吊子現學現用的人來說,會更加難以理解,所以必須要從簡單的地方入手。這里,我們的切入點就是enSecKey,為什么呢,因為無論你在里面如何修改,最終出口一定是含有params和enSecKey名字的參數,我們切到下面這個enSecKey位置
這里有個data關鍵字,里面正好是params,和enSecKey。
很大概率,這是這兩個函數的出口,我們看看源頭,往上面看一下,這是由v0x.bl1x這個函數加載的
來自,那么我們切回去剛剛那個找JS的地方看看。
十有八九就是這個函數。
那么接下重頭戲,我們開始閱讀這個JS
params和encText都是由bY14p這個函數發起的,上面定義了這個一個BY14p函數,我們先不管windows.asrsea是啥,先看后面的幾個參數。
var bYl4p = window.asrsea(JSON.stringify(i0x), bqv4z(["流淚", "強"]), bqv4z(QI7B.md), bqv4z(["愛心", "女孩", "驚恐", "大笑"]));
這里有4個參數,我們稱之為第一參數、第二參數、第三參數、第四參數
第一參數:JSON.stringify(i0x)
第二參數:bqv4z(["流淚", "強"])
第三參數: bqv4z(QI7B.md)
第四參數: bqv4z(["愛心", "女孩", "驚恐", "大笑"])
第二個和第四個參數,我們一眼就看得出,這是傳入實參,在python里我們也知道,這一定是個定值。不信你們可以去翻閱一下bqv4z的加密方式,不過等等,我們再看第三個參數,QI7B.md是啥,我們去看看
這也是一個實參,那么真相只有一個,那就是第一參數一定是個變化的參數。
這里需要打住,如果我們要繼續研究下去,有兩種發展思路,一個是閱讀JS,破解JS加密重構Python代碼。這個難度,就算是學幾年爬蟲的人估計都不一定達到。第二種,為了不繞進設計者的加密思路中,我們要用另外一種手段取得加密參數,在這里,我介紹第二種方法,因為人家設計者想盡辦法讓你繞暈,你為什么一定要跟別人的長處較勁呢,于是,我在這里隆重推薦這個抓包工具Charles
Charles的使用介紹比較復雜,你們可以自行去搜索教程安裝,有可能我另起一個安裝教程,不過簡單的來說,就是要你的瀏覽器安裝證書(或者手機)因為Charles默認只支持http,所以你要適當進行設置。Charles怎么說呢,就像是一個中介,在實現服務器和你的電腦端交互的時候,Charles作為中間過濾器給你篩選信息。
好了,我現在就當你準備好。
用Charles我推薦用
火狐瀏覽器
回到上文,現在,我需要重寫JS代碼,在不影響整體運行的情況下,我需要知道,傳入的這幾個參數的運行結果分別是什么
因此,我在這里加入一個alert語法彈出這幾個參數的運行結果
#知道你們懶了
alert(JSON.stringify(i0x)+"=="+bqv4z(["流淚", "強"])+"=="+bqv4z(QI7B.md)+"=="+bqv4z(["愛心", "女孩", "驚恐", "大笑"]))
第一步,我們找到JS地址中那個core c245e96...的地址,我們瞧瞧,是在s3.music.126/web/s里面。然后我們打開小葉壺
如果你找不到這個地方,或者顯示unknown,不用懷疑,你一定是小葉壺哪里設置出問題了,趕緊去解決吧!
接下來是重點
對著這個core的JS文件,右鍵,最下面有個Map Local,點開彈出這個界面,把我們修改好的JS文件更改進去,確定。
我們再刷新一下火狐頁面
你會發現這幾個參數對應的內容都顯示出來了,我把原彈框復制出來,然后分割
{"rid":"R_SO_4_478106252","offset":"20","total":"false","limit":"20","csrf_token":""}==010001==00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7==0CoJUm6Qyw8W8jud
我這里給的是第二頁的參數,因為第0頁第一參數不具代表性,這個東西,只要你做多了你就下意識明白,我也很難說明。
規整化后,你就會發現這幾個參數分別是
第一參數:{"rid":"R_SO_4_478106252","offset":"20","total":"false","limit":"20","csrf_token":""}
第二參數:010001
第三參數:00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7
第四參數:0CoJUm6Qyw8W8jud
好了,其實我說到這里,大家就可以接著看網上的破解結果,因為我覺得說到這里已經非常明白了,2、3、4是實參,這些數據不會變,變的是第一個,第一個傳入的都是些什么,如果你還沒懂,真的枉寫那么多爬蟲了,接下來該怎么做。網上已經提供了非常多的思路。
這里說漏了個東西,我們還要看windows.asrsea是什么東西,大家搜索關鍵字,然后在上面可以看到定義的一個變量window.asrsea = d
那么d又是什么鬼
,然后你會發現,d函數返回的就是encSecKey和encText,然后大家要想清楚這個問題,我們在之前定義了windows.asrsea的四個變量,然后他說windows.asrsea = d
那4個變量分別就是對應 d,e,f,g
關于encText,他要的是d,g兩個參數,還有個i,當然你問b又是什么,這些我們都不要去管,這一定是某種加密技術,我們現在只需要知道他傳入的是什么參數就行。
那么還有一個i,又是啥?
上面定義了,i =a(16)
a又是啥?
a呢,其實就是一個16位長度的隨機數
說完,那么encText里面含有什么呢
就是d+g+i
所以encSecKey同理:
params:第一參數 + 第四參數 + 16位長度的隨機數
encSecKey:16位長度隨機數 + 第二參數 + 第三參數
也就是說encSecKey其實是個常量,隨便拷貝一個data里面的數據直接用就完事了。