用Python爬虫爬取音乐!(附源码)

QQ音乐爬虫:歌曲链接获取分析
该文章已生成可运行项目,

QQ音乐相比于网易云音乐加密部分基本上没有,但是就是QQ音乐的页面与页面之间的联系太强了,,导致下载一个音乐需要分析前面多个页面,找数据。。太繁琐了

包含编程资料、学习路线图、源代码、软件安装包等!【点击领取】!

在这里插入图片描述

首先随便找一个页面先点进去

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就运行程序是输入就行

所有问题都解决了(呼~~~~~~~)
**

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()
本文章已经生成可运行项目
### 如何使用 Python 爬取 QQ 音乐数据 要实现通过 Python 抓取 QQ 音乐的数据,可以按照以下方法操作: #### 1. 数据获取方式 QQ 音乐通常会提供 API 接口用于前端页面加载所需的内容。这些接口可以通过浏览器开发者工具中的 **Network** 标签找到。当访问某个歌曲或者歌单详情页时,观察请求记录即可发现对应的 XHR 请求地址[^1]。 对于 JSON 格式的响应内容,在 Python 中可以直接利用 `requests` 库发送 HTTP 请求,并借助内置模块 `json.loads()` 将其解析为字典结构以便进一步处理[^2]。 ```python import requests def fetch_music_data(url, params=None): headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36' } response = requests.get(url=url, params=params, headers=headers) if response.status_code == 200: try: data = response.json() # 解析JSON格式返回值 return data except Exception as e: print(f"Error occurred while parsing json: {e}") return None else: print(f"Failed to retrieve data with status code {response.status_code}.") return None ``` #### 2. 处理评论数据 如果目标是从特定 URL 获取某首歌曲下的用户评论,则可以根据已知的参数模板构建完整的 GET 请求链接[^3]。下面是一个简单的例子展示如何分页读取指定数量的评论条目: ```python base_url = "https://c.y.qq.com/base/fcgi-bin/fcg_global_comment_h5.fcg" params_template = { 'g_tk': '2058499274', 'jsonpCallback': 'jsoncallback06927647062927766', 'loginUin': '2230661779', 'hostUin': '0', 'format': 'jsonp', 'inCharset': 'utf8', 'outCharset': 'GB2312', 'notice': '0', 'platform': 'yqq', 'needNewCode': '0', 'cid': '205360772', 'reqtype': '2', 'biztype': '1', 'topid': '{song_id}', # 替换为目标歌曲ID 'cmd': '8', 'needmusiccrit': '0', 'pagenum': '{page_num}', 'pagesize': '25', # 每次最多拉取25条评论 } all_comments = [] for i in range(10): # 假设只抓取前10页 current_params = dict(params_template) current_params['pagenum'] = str(i) result = fetch_music_data(base_url, current_params) comments_list = result.get('comment').get('list') all_comments.extend(comments_list or []) print(len(all_comments), "comments collected.") ``` 以上脚本实现了基本功能框架,实际应用过程中还需要注意异常情况以及可能存在的反爬机制等问题。 --- ####
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值