获取网易云音乐评论
首先分析可以得到網(wǎng)易云音樂的評論不是在網(wǎng)頁源代碼中存儲(chǔ)的,而是通過ajax異步請求得到的數(shù)據(jù),瀏覽器開啟F12,刷新網(wǎng)頁,發(fā)現(xiàn)這個(gè)請求返回的數(shù)據(jù)就是我們想找到的評論數(shù)據(jù)。
但是查看其請求頭卻發(fā)現(xiàn),請求的參數(shù)是加密過的,那么如何找到這個(gè)加密方法呢?
通過查看Initiator我們可以定位到發(fā)起這個(gè)請求的js文件
然后我們在這行打上斷點(diǎn),刷新界面,觀察變量的值,我們發(fā)現(xiàn)這個(gè)值已經(jīng)被加密處理過來,然后我們查看函數(shù)調(diào)用的堆棧,一個(gè)一個(gè)的分析,找到被加密的地方。
然后找到了加密的地方
其實(shí)window.asrsea就是函數(shù)d
那么這個(gè)時(shí)候我們已經(jīng)知道加密的js代碼了,此時(shí)只需將這段js代碼用python來實(shí)現(xiàn)即可。我們首先來看函數(shù)d的參數(shù),第一個(gè)參數(shù)d是將i9b這個(gè)變量轉(zhuǎn)成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" }第二個(gè)參數(shù)e,傳入的是bsP6J(["流淚", "強(qiáng)"])bsP6J是一個(gè)函數(shù)
var bsP6J = function(cxG5L) {var m9d = [];j9a.bg9X(cxG5L, function(cxF5K) {m9d.push(Xk6e.emj[cxF5K])});return m9d.join("")};我們直接打開瀏覽器的Console面板,運(yùn)行這個(gè)語句,發(fā)現(xiàn)得到的值都是一樣的,即字符串"010001"。那我們就聲明e = "010001"
按照此方法可以得到
至此,d函數(shù)的參數(shù)已經(jīng)全部確定。
接下來,我們先看函數(shù)d中的h.encSecKey的值是如何確定的, h.encSecKey = c(i, e, f),其中的i是由函數(shù)函數(shù)a返回的,查看函數(shù)a的代碼可以發(fā)現(xiàn)其功能就是返回一個(gè)長度為16的字符串,但是是隨機(jī)的,每次返回的結(jié)果是不一樣的,由此我們可以得出,在c函數(shù)中,這個(gè)變量i的值每次都不一樣,而e和f的值又是確定的,所以我們只要固定i是固定的,那么c函數(shù)返回的值也是固定的,所以我們直接取一次運(yùn)行的i值,代入函數(shù)c中,得到的encSecText作為我們的參數(shù)即可。改寫成python代碼如下:
接下來我們分析h.encText是如何得到的,先看函數(shù)b
function b(a, b) { # a是要加密的內(nèi)容, var c = CryptoJS.enc.Utf8.parse(b) # # b是秘鑰, d = CryptoJS.enc.Utf8.parse("0102030405060708"), e = CryptoJS.enc.Utf8.parse(a) # e是數(shù)據(jù), 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也是秘鑰就是將內(nèi)容進(jìn)行了兩次加密,兩次使用的密鑰不一樣,第二次加密的內(nèi)容就是第一次加密返回的結(jié)果作為參數(shù)傳入。而b函數(shù)查看代碼也看出了這個(gè)是AES加密,而python中也存在同樣的包,對此,可以將加密方法改裝成python代碼。
# 把參數(shù)進(jìn)行加密 def get_params(data): # 默認(rèn)這里接收到的是字符串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) # 創(chuàng)建加密器bs = aes.encrypt(data.encode("utf-8")) # 加密, 加密的內(nèi)容的長度必須是16的倍數(shù)return str(b64encode(bs), "utf-8") # 轉(zhuǎn)化成字符串返回,# 轉(zhuǎn)化成16的倍數(shù), 為下方的加密算法服務(wù) 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" }# 服務(wù)于d的 f = "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7" g = "0CoJUm6Qyw8W8jud" e = "010001" i = "d5bpgMn9byrHNtAh" # 手動(dòng)固定的. -> 人家函數(shù)中是隨機(jī)的def get_encSecKey(): # 由于i是固定的. 那么encSecText就是固定的. c()函數(shù)的結(jié)果就是固定的return "1b5c4ad466aabcfb713940efed0c99a1030bce2456462c73d8383c60e751b069c24f82e60386186d4413e9d7f7a9c7cf89fb06e40e52f28b84b8786b476738a12b81ac60a3ff70e00b085c886a6600c012b61dbf418af84eb0be5b735988addafbd7221903c44d027b2696f1cd50c49917e515398bcc6080233c71142d226ebb"# 把參數(shù)進(jìn)行加密 def get_params(data): # 默認(rèn)這里接收到的是字符串first = enc_params(data, g)second = enc_params(first, i)return second # 返回的就是params# 轉(zhuǎn)化成16的倍數(shù), 位下方的加密算法服務(wù) 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) # 創(chuàng)建加密器bs = aes.encrypt(data.encode("utf-8")) # 加密, 加密的內(nèi)容的長度必須是16的倍數(shù)return str(b64encode(bs), "utf-8") # 轉(zhuǎn)化成字符串返回,# 發(fā)送請求. 得到評論結(jié)果 resp = requests.post(url, data={"params": get_params(json.dumps(i9b)),"encSecKey": get_encSecKey() })print(resp.text)結(jié)果如下:
總結(jié)
- 上一篇: 智能制造学习纪录片和书籍
- 下一篇: 解剖点击量过亿的软文牛人是怎样炼成的?