如何下载QQ音乐里面收藏的歌曲
免责声明
- 此文章具有非常强的时效性。
- 本文只是技术思路分享,未实现完整程序,更不存在传播相关程序。
- 测试时下载的歌曲,也在测试完成后立即删除,并未进行传播保留。
前言
这几天失业了,QQ 音乐也正好提醒会员即将到期,显然是不会续费了。那么,有没有可能将已有的歌曲保存到本地,以便在失业潮里也能…。打住,版权,版权,还是版权,我们只做技术分析学习。
从哪里开始?
QQ 音乐有多种版本:PC/Mac 版、网页版、移动端版,显然,网页版是最容易进行技术分析的。
获取歌曲列表
在浏览器打开 https://y.qq.com/ 后登录,发现我的音乐音乐列表有限制,仅显示前 10 首。

查看 Network 接口,可以看到相关请求:
1 | // POST |
很容易看出,req_1.param.song_num 是控制返回歌曲数量的参数。
尝试通过 Postman 修改 song_num 参数值为 1000 后返回接口会报错。
通过多次测试确定是 sign=** 参数的原因,看样子页面在发送请求前会对请求参数进行一个签名计算,服务端进行验证。
尝试在 DevTools 中操作,在相关代码修改了song_num: 10 的值,后面代码再进行签名、发出请求,就可以成功获取到歌曲列表了。
下载歌曲
歌曲列表 API 并不包含歌曲文件地址,因此需要进入歌曲播放页面,通过 DevTools 查看网络请求,发现一个 GET 请求:
1 | https://**.stream.qqmusic.qq.com/**.m4a?guid=**&vkey=**&uin=**&fromtag=** |
返回了歌曲文件内容,保存为 m4a 文件后可以播放。
观察这个请求参数 发现关键难点参数是 vkey,他也是类似上面的 sign 参数,也是通过一些参数加算法处理得到的,服务端会进行验证。
实现思路
如果通过 httpClient 去实现这个程序,虽然执行效率会更高,但需要对诸多参数进行分析,还需要从压缩的 js 代码中扒取到相关算法代码,还可能遭遇验证码问题。考虑到这类需求功能通常只会用一两次,也不在乎这点执行效率,所以这个方案性价比太低。
那么选择使用 Selenium 或者 Puppeteer 来实现,性价比是最高的,只需要少量代码,少量调试即可快速搞定需求。
下面实例代码是
Puppeteer实现的。
步骤
- 登录授权
Puppeteer 打开 QQ 音乐,用户再手动登录。
- 获取歌曲列表
可以通过 request 事件,对指定 js 文件进行拦截,修改为本地 js 文件,本地文件对 song_num: 10 参数进行了修改。下面是示例代码。
1 | const likePage = await browser.newPage(); |
- 下载歌曲
页面渲染出歌曲列表后,我们通过以下代码,点击一首歌曲的播放按钮,打开播放页面。
1 | await likePage.evaluate( |
我们在播放页面的 request 事件中对请求的 url 进行判断,如果是歌曲文件,再通过 httpClient 下载保存到本地即可。保存成功再切换到下一首,直到歌曲列表全部下载完成。
以上就整个程序的实现思路了。
可能会遇到的坑
- 播放过的歌曲可能会缓存在浏览器的 IndexedDB 中,缓存过的歌曲不再进行网络请求。
- 歌曲列表中可能会遇到一些无版权的歌曲,需要判断进行跳过或先从列表中移除。
- 歌曲名、歌手名等可能存在特殊字符,用作文件名时需要进行处理。