這段時間聽歌少了,敲代碼的時候喜歡把喜馬拉雅FM廣播開啟。
既然在學習 Python ,就試著寫一個爬蟲,把喜馬拉雅上面的音頻爬下來。
分析了一下網站才發現爬喜馬拉雅上的音頻還是很容易的。
聲明:本文只是作為技術交流,切勿作為其他用途。
聲明:本文只是作為技術交流,切勿作為其他用途。
聲明:本文只是作為技術交流,切勿作為其他用途。 分析網站
擷取音頻檔案實質就是擷取音訊 URL
爬取這個網站我個人比較傾向先分析最後一步,然後在往前來分析。
也就是說,我們先來看一看最後一步播放時,抓包抓取網頁的傳回值,得到音頻資訊,最重要的也就是音訊 URL。 抓包
以下面這個頁面為例
http://www.ximalaya.com/91044493/album/11438377/
隨意開啟一個音訊播放介面,按下 F12 開啟開發人員工具,如果有內容了,就清空。然後點擊網頁上的播放按鈕。
可以看到網頁返回了一個 json 資料。
圖片紅色方框地區就是 音訊 URL ,我們找到了 URL ,這個程式就完成了一大半了。
開啟 headers 標籤,可以看到這個 json 資料的 URL
注意這個 URL 後面的這一串數字,這一串數字實際上就是這個音訊 ID,相當於人的社會安全號碼,是唯一的。實際上,我們只要拿到了每一個音訊 ID,就可以通過這個 ID 來擷取這個 json 資料,從而擷取到音訊 URL。我測試過,三個地址都是音頻URL。我們只要一個就好。
這個過程簡化就是 : ID -> json -> 音頻 url 找到音頻ID
查看網頁原始碼可以看到,每一個音訊 ID 實際上都已經寫在了網頁原始碼中。
那麼這個事情就變得很明了了。 寫代碼
還是從後往前做,我們先來寫通過 json 資料來擷取音頻 URL 並下載音訊函數。
def download(url): req = requests.get(url,headers = hd) # hd 為 user-agent result = req.text result = json.loads(result) title = result['title'] data_url = result['play_path_64'] data = requests.get(data_url).content with open('%s.m4a'%title,'wb') as f: f.write(data)
這裡傳的 url 參數是 json 資料的 url 。
現在就需要來構造 json 的 url ,那麼還需要做一些前期工作,就是先擷取音頻 ID。就以此頁面為例,就用正則就可以擷取到。
# http://www.ximalaya.com/tracks/66104267.json json 的 url 格式,不同的只是 IDdef get_id(url): req = requests.get(url, headers=hd) result = req.text id_number = re.findall('sound_id="([\d]*?)"',result) id_number = set(id_number) # 由於頁面上有重複的 ID,故利用集合的屬性去掉其重複的 ID id = [] for number in id_number: id.append('http://www.ximalaya.com/tracks/' + number + '.json') # 這樣構造url是不太嚴謹的,當然在這裡是可以的,以後再探討 url 的構造方法 return id
擷取了頁面所有音訊 ID ,構造了 json 的 url ,也寫好了下載音訊函數,那麼最後就差寫個迴圈將所有的音頻下載下來了。
for url in get_id('http://www.ximalaya.com/91044493/album/11438377/'): download(url)
總結
這個程式寫的很簡陋,用了三個模組 requests,re,json,代碼也不過30行左右,只能下載一個頁面的所有音頻。當然,如果願意話,可以寫的功能更加強大,那個就請讀者來根據需要私人定製了。因為在這個爬蟲裡面,最關鍵的部位已經得到解決了。爬取喜馬拉雅這個網站還是比較簡單的,主要就是抓包那一步,弄清楚資料的來源,很多問題就很簡單了。