python爬取QQVIP音樂


QQ音樂相比於網易雲音樂加密部分基本上沒有,但是就是QQ音樂的頁面與頁面之間的聯系太強了,,導致下載一個音樂需要分析前面多個頁面,找數據。。太繁瑣了

 

1、爬取鏈接:https://y.qq.com/

 

 

首先隨便找一個頁面先點進去

 

 

 

2、點擊播放歌曲會打開一個頁面,按F12打開控制台,然后刷新頁面並點擊播放歌曲,network里面就會有數據包

 

 

 

3、在控制台選中media,找到下圖這樣類型的文件,它的request url就是歌曲播放url,如下下圖

 

 

 

 

 

 

 

 

當然,我們肯定不能每下載一首歌都這樣,一是這樣很麻煩,二是遇到vip等音樂,你在線都不能播放,你還怎么找到歌曲鏈接

所以,分析頁面是必然的!!!我們首先分析一下這個歌曲播放鏈接的url

 

https://isure.stream.qqmusic.qq.com/C400002AskAI4LWf5i.m4a?guid=8487932120&vkey=65570474D22ADFAB32FE60DA30EA32CB618422B773A49AE5FA2158C071D4C51931D28B15D823E1BA87BCA837EC09A0FCF8BD9E2763D46B91&uin=0&fromtag=66

我們對這個url進行刪減(因為url有些部分都不需要,我們為了看起來更直觀要對其進行處理)

 

#精簡后url
https://isure.stream.qqmusic.qq.com/C400002AskAI4LWf5i.m4a?guid=8487932120&vkey=65570474D22ADFAB32FE60DA30EA32CB618422B773A49AE5FA2158C071D4C51931D28B15D823E1BA87BCA837EC09A0FCF8BD9E2763D46B91

 

我們大致一看它的url,就知道頁面提交用get將參數guid和vkey追加到url地址后面,那么我們就要去找vkey和guid參數是怎么來的

 

guid參數:

你多打開幾個歌曲就會發現它的guid都是一樣的,所以這個我們就不用管

 

vkey參數:

這個參數難為死我了,我剛開始以為它和網易雲音樂一樣也是加密一下,然后我就去js文件里面找,找了半天沒找到賦值語句,我就納悶了,以為這是更高級的加密,,,,然后看了半天js,最后終於確定,js和這個沒啥關系。。。。。。。

 

之后感覺分析頁面分析不動了,上網找了篇博客給了我靈感,雖然那篇博客代碼已經過時了,但是它啟發了我 “播放歌曲的鏈接可能不止一個”

於是我又開始找vkey在哪個數據包出現過,如下圖

 

我找到了vkey且對比了一下和之前鏈接上vkey的值一樣,你再仔細看就會發現那個歌曲下載鏈接就是

https://isure.stream.qqmusic.qq.com/加上purl的值。(我giao!!)

 

然后就要去分析這個數據包的請求頭了(嗚嗚嗚~),請求頭如下(好長~~~)

 

https://u.y.qq.com/cgi-bin/musics.fcg?-=getplaysongvkey6574047973093009&g_tk=1740745507&sign=zzaztgck8xaqpsxorw45ed952a339dbe91c7990f803cb9a6f1&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8&notice=0&platform=yqq.json&needNewCode=0&data=%7B%22req_0%22%3A%7B%22module%22%3A%22vkey.GetVkeyServer%22%2C%22method%22%3A%22CgiGetVkey%22%2C%22param%22%3A%7B%22guid%22%3A%228487932120%22%2C%22songmid%22%3A%5B%22003cGaJY10RAsX%22%5D%2C%22songtype%22%3A%5B0%5D%2C%22uin%22%3A%220%22%2C%22loginflag%22%3A1%2C%22platform%22%3A%2220%22%7D%7D%2C%22comm%22%3A%7B%22uin%22%3A0%2C%22format%22%3A%22json%22%2C%22ct%22%3A24%2C%22cv%22%3A0%7D%7D

 

這個時候我就遇到一個坑點(QQ音樂有毒),這么長的鏈接我們肯定要對其進行刪減,好看看哪些參數有用,哪些參數用來混亂我們的視線

但是如果你前面的一段鏈接改為

 

https://u.y.qq.com/cgi-bin/musicu

 

你就能對很多參數進行刪除,就最后一個字母不一樣,但是對參數進行刪除的時候前面那個鏈接就基本上參數都不能刪除

這讓我就很難受,我的訪問鏈接就是 

https://u.y.qq.com/cgi-bin/musics

 這一部分,但是有些人訪問鏈接是

 

https://u.y.qq.com/cgi-bin/musicu

 

 

化簡之后鏈接就變成了

 

https://u.y.qq.com/cgi-bin/musicu.fcg?format=json&data=%7B%22req_0%22%3A%7B%22module%22%3A%22vkey.GetVkeyServer%22%2C%22method%22%3A%22CgiGetVkey%22%2C%22param%22%3A%7B%22guid%22%3A%22358840384%22%2C%22songmid%22%3A%5B%22{}%22%5D%2C%22songtype%22%3A%5B0%5D%2C%22uin%22%3A%221443481947%22%2C%22loginflag%22%3A1%2C%22platform%22%3A%2220%22%7D%7D%2C%22comm%22%3A%7B%22uin%22%3A%2218585073516%22%2C%22format%22%3A%22json%22%2C%22ct%22%3A24%2C%22cv%22%3A0%7D%7D".format(mid值)
            

 

 

 

與其他歌曲的這個鏈接對比一下就會發現只有songmid的值再改變

我們再去找songmid是什么,瘋狂在文件中尋找,結果沒有songmid字樣,有也是在js中,songmid在js中還多以注釋出現。。。

 

之后我在搜索歌曲之后,在歌曲信息的數據包里面發現了mid,然后我把url地址中編碼過的mid解碼后發現它們一樣。。。(牛掰!!!)

下面給一個在多個文件中快速搜索關鍵子字的方法,如下圖:

 

在線url解碼:http://tool.chinaz.com/tools/urlencode.aspx

 

 

 

 

以搜索“夕陽紅為例”

 

 

 數據包list字段下面就是歌曲信息

 

 

 

 

 

 

然后再看一下這個數據包的請求頭(希望不要麻煩)

 

https://c.y.qq.com/soso/fcgi-bin/client_search_cp?ct=24&qqmusic_ver=1298&new_json=1&remoteplace=txt.yqq.song&searchid=70921863029222715&t=0&aggr=1&cr=1&catZhida=1&lossless=0&flag_qc=0&p=1&n=10&w=%E5%A4%95%E9%98%B3%E7%BA%A2&g_tk_new_20200303=1740745507&g_tk=1740745507&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8&notice=0&platform=yqq.json&needNewCode=0

 

 

 

刪減之后

https://c.y.qq.com/soso/fcgi-bin/client_search_cp?ct=24&qqmusic_ver=1298&new_json=1&remoteplace=txt.yqq.song&searchid=70631360004412645&t=0&aggr=1&cr=1&catZhida=1&lossless=0&flag_qc=0&p=1&n=10&w=%E9%9D%9E%E9%B1%BC&g_tk_new_20200303=5381&g_tk=5381&loginUin=2272463882&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8&notice=0&platform=yqq.json&needNewCode=0

 

通過歸納可以知道n代表搜索到的歌曲顯示數目,w是搜索的關鍵字

所以我們n設定一個值就行,w就運行程序是輸入就行

所有問題都解決了(呼~~~~~~~)

 

 

代碼(代碼借鑒於:https://blog.csdn.net/qq_43814415/article/details/106786012?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-6.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-6.channel_param

 

import requests
import re
import os
import json
import time as t


class QQmusic():
    """代碼僅供學習"""

    def __init__(self):
        """初始化"""
        self.headers = {
            'Accept-Encoding': 'gzip, deflate, sdch',
            'Accept-Language': 'en-US,en;q=0.8',
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36',
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
            'Referer': 'http://www.baidu.com/',
            'Connection': 'keep-alive',
        }
        self.names = []
        self.order = ' '

    def search(self):
        """搜索"""
        w = input("請輸入歌曲名: ")
        url_0 = "https://c.y.qq.com/soso/fcgi-bin/client_search_cp?ct=24&qqmusic_ver=1298&new_json=1&remoteplace=txt.yqq.song&searchid=61460539676714578&t=0&aggr=1&cr=1&catZhida=1&lossless=0&flag_qc=0&p=1&n=10&w={0}&g_tk_new_20200303=5381&g_tk=5381&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8&notice=0&platform=yqq.json&needNewCode=0".format(
            w)
        res_0 = requests.get(url_0, headers=self.headers)  # 第一層,搜索頁
        res_0.encoding = res_0.apparent_encoding
        res_0 = res_0.json()  # dict
        music_list = res_0["data"]["song"]["list"]
        print("共計" + str(len(music_list)) + "結果: ")

        all_singers = []
        a = 0
        for music in music_list:
            singer = music["singer"][0]["title"]  # 歌手名
            name = str(a) + "  " + music["title"]  # 歌曲名
            all_singers.append(singer)
            self.names.append(name)
            a = a + 1
        infs = dict(zip(self.names, all_singers))
        infs = json.dumps(infs, ensure_ascii=False, indent=4, separators=(',', ':'))
        infs = infs.replace('"', ' ')
        infs = infs.replace(':', '——————')
        print(infs)

        self.order = input("請輸入歌曲前的序號:")
        songmid = res_0['data']['song']['list'][int(self.order)]['mid']
        url_1 = "https://u.y.qq.com/cgi-bin/musicu.fcg?format=json&data=%7B%22req_0%22%3A%7B%22module%22%3A%22vkey.GetVkeyServer%22%2C%22method%22%3A%22CgiGetVkey%22%2C%22param%22%3A%7B%22guid%22%3A%22358840384%22%2C%22songmid%22%3A%5B%22{}%22%5D%2C%22songtype%22%3A%5B0%5D%2C%22uin%22%3A%221443481947%22%2C%22loginflag%22%3A1%2C%22platform%22%3A%2220%22%7D%7D%2C%22comm%22%3A%7B%22uin%22%3A%2218585073516%22%2C%22format%22%3A%22json%22%2C%22ct%22%3A24%2C%22cv%22%3A0%7D%7D".format(songmid)

        res_1 = requests.get(url_1, headers=self.headers)
        res_1.encoding = res_1.apparent_encoding
        res_1 = res_1.json()  # dict
        purl = res_1['req_0']['data']['midurlinfo'][0]['purl']
        url_2 = "https://isure.stream.qqmusic.qq.com/" + purl
        return url_2

    def download(self):
        """下載"""
        res_2 = requests.get(self.search(), headers=self.headers).content
        fir = self.names[int(self.order)]
        tit = re.sub(r'\d+', '', fir)
        now = os.getcwd()
        now = os.path.join(now, "qq音樂 ")
        if not os.path.exists(now):
            os.mkdir(now)
        os.chdir(now)
        file_name = tit + '.m4a'
        with open(file_name, 'wb') as f:
            f.write(res_2)


one_file = QQmusic()
one_file.download()

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM