Python下載會員歌曲

Python下載會員歌曲

@(博客)[QQ|會員音樂|下載]python

018.8.8git

1. 因爲本人是法盲,因此是否涉及侵權QQ音樂不知;如若侵權,相告即刪
2. 相關代碼僅做參考學習,不用於商業目的github

前言

原本想先編個故事再進入正文的,這符合個人風格。但因爲要下載QQ音樂的VIP歌曲,代碼方面不難,而是分析文件的過程有點繞。我已經以爲這個過程我會說不清楚,繼而意興闌珊,故事什麼的就了無趣味了chrome


目標

QQ音樂中VIP才能下載的歌曲瀏覽器

使用庫

主要使用的庫:
- requests 向服務器發起請求
- urllib 構建url地址
- re 提取須要的數據服務器

分析

(1)文件A

首先咱們來到QQ音樂的網頁端,播放一首歌曲,這裏就以【小半】爲例
這裏寫圖片描述工具

利用chrome的開發者工具,勾選Preserver log,而且選中Media,刷新頁面
這裏寫圖片描述學習

刷新頁面
這裏寫圖片描述測試

此時會發現有這麼一個不知道什麼的文件出現,暫且稱之爲文件A。右下角紅色方框內是請求這個數據時帶上的query參數url

點進來以後會發現其實這就是咱們須要的歌曲文件
這裏寫圖片描述

因此如今的問題成了如何請求文件A。咱們已經有了請求參數,也能夠找到服務器的接口
這裏寫圖片描述

根據反覆測試,發現只有關鍵字vkey的值在發生變化,因此只要咱們獲取了動態變化的vkey值,拿到文件A就易如反掌了


(2)文件B

經過開發者工具,我找到了一個JS文件,暫且稱之爲文件B,它在歌曲文件以前被請求,而且其返還數據裏面有vkey
這裏寫圖片描述

咱們也發現,須要請求這個文件,須要的query參數不可謂少
這裏寫圖片描述

一樣,在反覆測試之後會發現,songmid的值會根據歌曲的不一樣而發生改變;filename的值是在songmid值的左邊加上C400,右邊加上.m4a

因而問題變成了如何獲取songmid的值


(3)文件C

繼續順藤摸瓜前邊的文件,在一個JS文件,暫且稱之爲文件C中找到了
這裏寫圖片描述

仔細分析會發現,關鍵字list是包含了【小半】所在專輯《小夢大半》裏面的所有歌曲,而還有個關鍵字singername是歌手名字,爲了確保咱們下載的歌曲是咱們想要的歌手唱的,因此我用正則提取出來。針對list,個人方法是將整個專輯中全部歌曲的songmid以及歌曲的名字所有提取出來,而後再從中確認咱們須要的songmid

# 提取歌手名字
SINGER = re.search(r'"singername":"(.+?)"', data).group(1)
# 提取專輯中全部的songmid,以及對應的歌曲名字

results = re.findall(r'"songmid":"(\w+?)","songname":"(.+?)"', data)

# 咱們知道,經過findall()方法獲得的結果是由元組組成的列表(如:[(songmid1, songname1), (songmid2, songname2),...]),因此對其遍歷,當歌曲名字SONGNAME在這個元組裏邊時,返回對應的songmid
if results:
    for result in results:
        if SONGNAME in result:
            return result[0]
    else:
        return None
else:
    return None

而如何得到這個文件呢?
這裏寫圖片描述
能夠看到,獲取這個文件的關鍵點是albummid的值


(4)文件D

來到QQ音樂的搜索界面
這裏寫圖片描述

當咱們在搜索框中鍵入文字之後點擊右邊的搜索按鈕,會發現瀏覽器接收到一個文件,我稱之爲文件D
這裏寫圖片描述

文件D中的list裏邊就包含了咱們搜索出來的結果,由於存在歌曲同名啊,翻唱之類的,因此通常list裏邊都包含多個值,而通常狀況下,比較火的歌,且在QQ音樂中有版權的,都會存放在第一個(若是有其餘目的,可自行在list的數據中進行取捨),這裏我就只取出第一個
這裏寫圖片描述

# 提取albummid的值
result = re.search(r'"mid":"(\w+?)"', data)
if result:
    return result.group(1)
else:
    return None

文件D的請求方式就比較簡單了
這裏寫圖片描述

儘管須要的參數不少,但最重要的就是w了,它對應的是歌曲名字

(5)注意事項

此時再回去看看請求文件A的接口,其實有一部分就是文件B中的關鍵字filename所對應的值,因此咱們對這個接口要動態改變

# 構建下載歌曲的query參數
PARAMS_FOR_VIPSONG["vkey"] = vkey
url = parse.urljoin(URL_FOR_VIPSONG, "C400"+songmid+".m4a?")

最後

分析是從裏到外,找到的文件是A->B->C->D;而代碼的執行順序應該是從外到裏,請求文件的順序是D->C->B->A

如下是我代碼的主要結構
這裏寫圖片描述

爲了更加友好,我另寫了一個main.py的文件,來提示程序的用法
這裏寫圖片描述

代碼運行效果以下
這裏寫圖片描述

完整代碼已上傳Github(有詳細註釋)

相關文章
相關標籤/搜索