本篇文章涉及內容包括:Python,爬蟲,json解析,request 庫的使用
前幾天刷B站無意中又刷到了一首神曲,“I Want My Tears Back”,挺好聽的。聽了幾遍後便尋思著能不能把這歌給下到手機上拿來當鬧鐘的,聽過的同學應該知道這歌有多提神,哈哈哈~~~ 沒聽過的同學可以點選文章上方的音樂,感受一下下。
接下來,當然要選擇一下從哪個平臺下搞這首歌回來啦。網易雲音樂和QQ音樂,選擇哪個?那就從網易雲入手吧,畢竟用的多些,接著便去網易雲一頓操作,此處省略1000字描述。發現,哎呦,這網易雲……不好搞呀。所以先不管了,看一下QQ音樂的情況先。 F12大法一開,QQ音樂就先給我來了個驚喜,大大符號圖示傾情相送。對比雲村的就沒有啦。
撇開這些不關鍵的東西不說了,接下來就是搜尋一首歌。這個時候,先把控制檯切到network欄,這個時候,你會發現左下角有很多請求連結。請求各種各樣的內容,這個時候,這些東西對我們都是沒用的,是吧。我們要的是我們請求搜尋那一瞬間他發出去的資料。所以,為了避免無關資料的干擾,建議點選左上角的清空把記錄清空先。然後右上角勾上disable cache,避免快取使我們看不到我們要的資料。
ok,這個時候我們輸入我們要查的歌,I Want My Tears Back。我們已經可以看到有東西已經發出去並返回回來了。就是這個連結我們觀察一下,這裡面的引數,key就有I Want My Tears Back這個歌名了,再看一下返回資料。是一個json資料,有很多內,我們可以很容易看出了資料包含了 專輯、mv、歌手、歌曲 這四大區域。我們關注歌曲這個欄,在count 中已經表明找到了兩首符合度最高的歌曲。一首是Nightwish的一首是Hok-key的。因為我想要的就是 夜願 這個版本的,所以我們就預設第一首出現的就是我們要下的歌曲哈。
這個時候,拿到這些資料有什麼用呢?歌曲連結還沒不知道怎麼構造呀。。。 先別急,我們看看歌曲連結長啥樣。然後………… 好尷尬呀,有木有,這,這誰忍得住呀?所以,機智的我開啟了另外一首歌…… 瞬間右邊記錄出來了一大堆,沒錯是一大堆東西……但是,控制檯有分類呀,不慫。選擇media分類,就給我們過濾出了那幾個連結。沒辦法了,逐個點選。1分鐘過後,I got it.最後那個連結就是歌曲連結。
可以清楚看到有幾個關鍵引數。guid、vkey、uin、fromtag,我們先暫且不管那個引數可以省略好吧。先看看可以從哪裡找到這幾個引數……又得看連結的返回值了(此處說明,可以在控制檯點選response標籤檢視返回值,你只要按↓鍵就OK了)。在漫長的遍歷過程中,我注意到了一個連結的內容十分不一樣的,不相同的,很多很多。直覺告訴我,就是這個連結了。
拿去做一下URL解碼後,咋一看一頭霧水。不信你看一下下?
接合歌曲連結,這個請求連結,搜尋請求結果,這三個內容。其實不難發現,songmid 這個引數是關鍵。
所以,我們這個時候基本就以及釐清下載音樂的步驟以及思路了。首先,請求搜尋某一首歌,然後或者到song mid 接著song mid 去請求伺服器拿到這首歌的播放連結。接著用request請求資料回來再用二進位制儲存就OK啦。
構造一個類,downloadMusic,初始化一個headers,做個最簡單的反爬。
寫run方法,將上面的思路實現出來。請求回資料後就用json.loads方法載入json資料。逐步逐步請求伺服器,填充需要填的資料。
最後拿到連結的URL後,就easy了,用requests請求資源回來後。用.content,不要用.text。又人問過我這兩個方法的區別。
簡單來說,content拿到的資料是位元組,除錯列印出來你會發現資料前面會有個b',text的話,就是一個字串了。
因為我們要儲存歌曲,就肯定要用位元組儲存好,用wb方式開啟,然後寫進去後便關閉即可。程式碼貼在下面。
至此寫完收工,可以美滋滋地下載我們要的歌了。有了它還怕什麼鈴聲找不到自己喜歡的問題嗎?
# -*- coding: utf-8 -*-
# @Time : 10/10/2018 9:31 PM
# @Author : MARX·CBR
# @File : __init__.py
import requests
import json
class downloadMusic:
def __init__(self):
self.headers = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
'Accept-Encoding': 'gzip, deflate',
'Accept-Language': 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3',
'Upgrade-Insecure-Requests': '1',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0',
}
self.name='I Want My Tears Back'
def run(self,sn):
self.name=sn
session=requests.session()
firstjsonurl='https://c.y.qq.com/splcloud/fcgi-bin/smartbox_new.fcg?is_xml=0&format=jsonp&key={}&g_tk=5381&jsonpCallback=SmartboxKeysCallbackmod_top_search1467&loginUin=0&hostUin=0&format=jsonp&inCharset=utf8&outCharset=utf-8¬ice=0&platform=yqq&needNewCode=0'.format(self.name)
r=session.get(firstjsonurl).text
print(type(r))
print(r[39:-1:])
myjson=json.loads(r[39:-1:])
mid=myjson['data']['song']['itemlist'][0]['mid']
print(mid)
searchurl='''https://u.y.qq.com/cgi-bin/musicu.fcg?callback=getplaysongvkey2236996910208997&g_tk=5381&jsonpCallback=getplaysongvkey2236996910208997&loginUin=0&hostUin=0&format=jsonp&inCharset=utf8&outCharset=utf-8¬ice=0&platform=yqq&needNewCode=0&data={"req":{"module":"CDN.SrfCdnDispatchServer","method":"GetCdnDispatch","param":{"guid":"8665097290","calltype":0,"userip":""}},"req_0":{"module":"vkey.GetVkeyServer","method":"CgiGetVkey","param":{"guid":"8665097290","songmid":["'''+mid+'''"],"songtype":[0],"uin":"0","loginflag":1,"platform":"20"}},"comm":{"uin":0,"format":"json","ct":20,"cv":0}}'''
r=session.get(searchurl).text
print(r)
songjson=json.loads(r[32:-1:])
print(songjson)
header=songjson['req_0']['data']['sip'][0]
two=songjson['req_0']['data']['midurlinfo'][0]['purl']
songurl=header+two
with open("{}.mp3".format(self.name),'wb') as ms:
print(songurl)
raw = session.get(songurl, headers=self.headers)
content=raw.content
if len(content) >500:
ms.write(content)
print("下載成功")
else:
print("下載失敗")
App=downloadMusic()
while 1:
songName=input("請輸入歌曲名字")
App.run(songName)
複製程式碼
效果如下: