今天給大家帶來的是網易雲音樂批量下載,代碼有些粗糙,以后有時間再慢慢改進。我只爬取了某個明星的全部歌曲,如果再添加點代碼完全可以爬取整站音樂,但是我認為還是點到為止,剩下的代碼也不難。首先,通過網頁抓包獲取真實音樂文件的鏈接,然后找到該提交地址,並分析傳入的 data 。比較走運的是,網上有很多關於獲取 encSecKey和 params 的教程,大家可以搜索一下。
一、抓包
我們的目的是獲取到真實的 URL 地址,可以看到 post 訪問該網址,可以返回真實的 URL 。
二、分析
post 提交的有兩個參數,但是被加密過!我們可以通過全局查找,找 params 和 encSecKey 參數,看它倆是從哪里蹦出來的!
通過查找,出現一大批文件,都是含有這兩個關鍵詞的,==!(慢慢找吧)。但是我們可以試試 encSecKey 這個參數。
這個比較少,拿這個下手。
經過一番搜索,找到很敏感的東西,兩個加密參數同時出現。接着找到這個函數...(js分析過程就不贅述了,網上有好多)。js分析過程:https://www.zhihu.com/question/36081767。通過分析 js ,我們得知通過給 js 傳入參數,就會獲取到兩個參數的加密值。我們把這個 js 打包,使用 python 調用,就可以獲取到兩個參數了。
三、敲代碼
import requests import re import execjs import json class Down(object): def __init__(self): pass # 獲取音樂文件的 ids 參數 def getids(self): _headers = {'Referer': 'https://music.163.com/', 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko'} # 通過該鏈接,獲取該頁面的源碼。 html = requests.get('https://music.163.com/artist?id=3685', headers=_headers).text # 返回通過正則匹配獲得的所有 ids 值。 return re.findall('<li><a.href=.*?song.*?id=(.*?)">(.*?)</a></li>', html) # 計算 ids 的加密后的值(通過引入js文件,計算相應的值) def countids(self,ids): # 傳入的參數,這里指的是獲取音樂URL時,需要傳入含有該音樂文件ids的字符串。 ddd = '{"ids":"['+ids+']","level":"standard","encodeType":"aac","csrf_token":""}' # 導入js文件 f=open('countdis.js','r',encoding='utf-8') line = f.readline() htmlstr = '' while line: htmlstr = htmlstr + line line = f.readline() ctx = execjs.compile(htmlstr) f.close() # 運行js的 d 函數,並傳入參數 ddd,也就是剛才定義的完整字符串,並返回。 return ctx.call('d', ddd) # 獲取到該音樂的真實 url 地址 def geturl(self): # 因為該頁面有多個音樂,會生成多個加密文本,所以這里迭代出來。 for i in self.getids(): # getids返回的是含有params 和 encSecKey兩個加密文的,所以通過列表獲取到相應的值。 str=self.countids(i[0]) encSecKey=str[0] params=str[1] _headers={'Referer':'https://music.163.com/', 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36' } _data={'encSecKey':encSecKey,'params':params} # 把獲取到的兩個參數值,提交到服務器,獲得 URL 地址。 urltext=requests.post('https://music.163.com/weapi/song/enhance/player/url/v1?csrf_token=',headers=_headers,data=_data).text _json=json.loads(urltext) url=_json['data'][0]['url'] # 獲得URL后,直接使用get下載音樂文件到本地。 data=requests.get(url,_headers,stream=True) with open(i[1]+'.mp3','wb') as f: for j in data.iter_content(chunk_size=512): f.write(j) print(i[1]+'.mp3 寫出完畢!') # 運行 if __name__=='__main__': bb=Down() bb.geturl()
* 我們最開始訪問的“https://music.163.com/artist?id=3685”是某個歌星的全部歌曲的頁面,需要抓包獲取。
四、運行以上代碼,得到音樂文件。
五、python源碼 和 js代碼請關注公眾號:PyShadow,在后台回復“1”獲取。