获取网易云音乐评论
首先分析可以得到網易云音樂的評論不是在網頁源代碼中存儲的,而是通過ajax異步請求得到的數據,瀏覽器開啟F12,刷新網頁,發現這個請求返回的數據就是我們想找到的評論數據。
但是查看其請求頭卻發現,請求的參數是加密過的,那么如何找到這個加密方法呢?
通過查看Initiator我們可以定位到發起這個請求的js文件
然后我們在這行打上斷點,刷新界面,觀察變量的值,我們發現這個值已經被加密處理過來,然后我們查看函數調用的堆棧,一個一個的分析,找到被加密的地方。
然后找到了加密的地方
其實window.asrsea就是函數d
那么這個時候我們已經知道加密的js代碼了,此時只需將這段js代碼用python來實現即可。我們首先來看函數d的參數,第一個參數d是將i9b這個變量轉成json的字符串,因此我們在python中定義同樣的變量即可。
i9b = {"csrf_token": "","cursor": "-1","offset": "0","orderType": "1","pageNo": "1","pageSize": "20","rid": "R_SO_4_1901371647","threadId": "R_SO_4_1901371647" }第二個參數e,傳入的是bsP6J(["流淚", "強"])bsP6J是一個函數
var bsP6J = function(cxG5L) {var m9d = [];j9a.bg9X(cxG5L, function(cxF5K) {m9d.push(Xk6e.emj[cxF5K])});return m9d.join("")};我們直接打開瀏覽器的Console面板,運行這個語句,發現得到的值都是一樣的,即字符串"010001"。那我們就聲明e = "010001"
按照此方法可以得到
至此,d函數的參數已經全部確定。
接下來,我們先看函數d中的h.encSecKey的值是如何確定的, h.encSecKey = c(i, e, f),其中的i是由函數函數a返回的,查看函數a的代碼可以發現其功能就是返回一個長度為16的字符串,但是是隨機的,每次返回的結果是不一樣的,由此我們可以得出,在c函數中,這個變量i的值每次都不一樣,而e和f的值又是確定的,所以我們只要固定i是固定的,那么c函數返回的值也是固定的,所以我們直接取一次運行的i值,代入函數c中,得到的encSecText作為我們的參數即可。改寫成python代碼如下:
接下來我們分析h.encText是如何得到的,先看函數b
function b(a, b) { # a是要加密的內容, var c = CryptoJS.enc.Utf8.parse(b) # # b是秘鑰, d = CryptoJS.enc.Utf8.parse("0102030405060708"), e = CryptoJS.enc.Utf8.parse(a) # e是數據, f = CryptoJS.AES.encrypt(e, c, { # c 加密的秘鑰iv: d, # 偏移量mode: CryptoJS.mode.CBC # 模式: cbc});return f.toString()} h.encText = b(d, g) # g秘鑰 h.encText = b(h.encText, i) # 返回的就是params i也是秘鑰就是將內容進行了兩次加密,兩次使用的密鑰不一樣,第二次加密的內容就是第一次加密返回的結果作為參數傳入。而b函數查看代碼也看出了這個是AES加密,而python中也存在同樣的包,對此,可以將加密方法改裝成python代碼。
# 把參數進行加密 def get_params(data): # 默認這里接收到的是字符串first = enc_params(data, g)second = enc_params(first, i)return second # 返回的就是params# 加密過程 def enc_params(data, key):iv = "0102030405060708"data = to_16(data)aes = AES.new(key=key.encode("utf-8"), IV=iv.encode('utf-8'), mode=AES.MODE_CBC) # 創建加密器bs = aes.encrypt(data.encode("utf-8")) # 加密, 加密的內容的長度必須是16的倍數return str(b64encode(bs), "utf-8") # 轉化成字符串返回,# 轉化成16的倍數, 為下方的加密算法服務 def to_16(data):pad = 16 - len(data) % 16data += chr(pad) * padreturn data所有代碼如下
# 需要安裝pycrypto: pip install pycrypto #coding = utf-8 from Crypto.Cipher import AES from base64 import b64encode import requests import jsonurl = "https://music.163.com/weapi/comment/resource/comments/get?csrf_token="# 請求方式是POST i9b = {"csrf_token": "","cursor": "-1","offset": "0","orderType": "1","pageNo": "1","pageSize": "20","rid": "R_SO_4_1901371647","threadId": "R_SO_4_1901371647" }# 服務于d的 f = "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7" g = "0CoJUm6Qyw8W8jud" e = "010001" i = "d5bpgMn9byrHNtAh" # 手動固定的. -> 人家函數中是隨機的def get_encSecKey(): # 由于i是固定的. 那么encSecText就是固定的. c()函數的結果就是固定的return "1b5c4ad466aabcfb713940efed0c99a1030bce2456462c73d8383c60e751b069c24f82e60386186d4413e9d7f7a9c7cf89fb06e40e52f28b84b8786b476738a12b81ac60a3ff70e00b085c886a6600c012b61dbf418af84eb0be5b735988addafbd7221903c44d027b2696f1cd50c49917e515398bcc6080233c71142d226ebb"# 把參數進行加密 def get_params(data): # 默認這里接收到的是字符串first = enc_params(data, g)second = enc_params(first, i)return second # 返回的就是params# 轉化成16的倍數, 位下方的加密算法服務 def to_16(data):pad = 16 - len(data) % 16data += chr(pad) * padreturn data# 加密過程 def enc_params(data, key):iv = "0102030405060708"data = to_16(data)aes = AES.new(key=key.encode("utf-8"), IV=iv.encode('utf-8'), mode=AES.MODE_CBC) # 創建加密器bs = aes.encrypt(data.encode("utf-8")) # 加密, 加密的內容的長度必須是16的倍數return str(b64encode(bs), "utf-8") # 轉化成字符串返回,# 發送請求. 得到評論結果 resp = requests.post(url, data={"params": get_params(json.dumps(i9b)),"encSecKey": get_encSecKey() })print(resp.text)結果如下:
總結
- 上一篇: 智能制造学习纪录片和书籍
- 下一篇: 解剖点击量过亿的软文牛人是怎样炼成的?