支持正版 人人有责
项目需求
① 模拟QQ音乐网页中的搜索和下载功能:
- 输入歌手或歌名搜索出相关的歌曲列表,然后可选下载。
- 可以将歌曲下载到本地。下载到本地的命名方式为:歌名+歌手+id。
一、首先去QQ音乐寻找音频下载接口:
随便搜索一首歌:
然后打开Chrome浏览器的开发者工具,同时点击播放歌曲:
接下来找到media类型的文件,显然我们要的音乐就是最大的那个文件,点开它:
打开这个URL:
至此,我们就成功找到了QQ音乐的音频下载接口。
二、分析音乐下载接口:
https://isure.stream.qqmusic.qq.com/C400003y3tQK2JZaau.m4a?
guid=4441071008&
vkey=6A1D99170713A9FFA58B61103D38450398E41C3ACDABF3F3E6FF170FB936B9239C1412F189015FE08484D930C1F11B39CD37EA7443CFC395&
uin=0&
fromtag=66
先分析一下这首歌的songmid参数
:
可以看到这首歌的songmid参数
是003y3tQK2JZaau
,是URL的C400
后面的部分。
songmid
从命名角度看,是歌曲的唯一标识符
而其余的参数在音频文件上就可以找到:
三、接下来分析搜索接口:
打开搜索框,输入歌曲名字,拦截搜索请求:
接下来对该URL进行解码:
分析一下URL里面的参数,以剔除一些不必要的参数:
https://c.y.qq.com/soso/fcgi-bin/client_search_cp?
ct=24&
qqmusic_ver=1298&
new_json=1&
remoteplace=txt.yqq.top&
searchid=35829660933924128&
t=0&
aggr=1&
cr=1&
catZhida=1&
lossless=0&
flag_qc=0&
p=1&
n=10&
w=你要相信这不是最后一天&
g_tk_new_20200303=1944343149&
g_tk=1944343149&
loginUin=0&
hostUin=0&
format=json&
inCharset=utf8&
outCharset=utf-8&
notice=0&
platform=yqq.json&
needNewCode=0
这里发现搜索的关键字就是w参数
。
剔除不必要的参数之后,如下:
https://c.y.qq.com/soso/fcgi-bin/client_search_cp?&t=0&aggr=1&cr=1&catZhida=1&lossless=0&flag_qc=0&p=1&n=10&w=
歌曲或歌手名称
四、通过搜索接口提取信息:
import requests
import json
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36'}
url = 'https://c.y.qq.com/soso/fcgi-bin/client_search_cp?&t=0&aggr=1&cr=1&catZhida=1&lossless=0&flag_qc=0&p=1&n=20&w=你要相信这不是最后一天'
response = requests.get(url, headers=headers)
js1 = json.loads(response.text.strip('callback()'))
js1 = js1['data']['song']['list']
print(js1)
Output:
这样,我们就成功提取歌曲信息了。
然后构建列表把相关信息存入即可:
medias = []
song_mid = []
src = []
song_names = []
singers = []
for rest in js1:
medias.append(rest['media_mid'])
song_mid.append(rest['songmid'])
song_names.append(rest['songname'])
singers.append(rest['singer'][0]['name'])
但我们从这里只是提取到了songmid参数
,要想下载歌曲,还得提取到vkey参数
。
五、通过下载接口获取vkey参数:
https://c.y.qq.com/base/fcgi-bin/fcg_music_express_mobile3.fcg?&jsonpCallback=MusicJsonCallback&cid=205361747&songmid=
通过这个接口,我们可以获取vkey参数
:
for n in range(0, len(medias)):
url2 = 'https://c.y.qq.com/base/fcgi-bin/fcg_music_express_mobile3.fcg?&jsonpCallback=MusicJsonCallback&cid=205361747&songmid=' + song_mid[n] + '&filename=C400' + medias[n] + '.m4a&guid=4441071008'
rest2 = get_request(url2)
# print(rest2.text)
js2 = json.loads(rest2.text)
print(js2)
六、通过下载接口下载歌曲:
for n in range(0, len(medias)):
try:
url2 = 'https://c.y.qq.com/base/fcgi-bin/fcg_music_express_mobile3.fcg?&jsonpCallback=MusicJsonCallback&cid=205361747&songmid=' + song_mid[n] + '&filename=C400' + medias[n] + '.m4a&guid=4441071008' # 重要参数提取接口
rest2 = self.get_request(url2)
js2 = json.loads(rest2.text)
vkey = js2['data']['items'][0]['vkey']
src.append('https://isure.stream.qqmusic.qq.com/C400' + medias[n] + '.m4a?vkey=' + vkey + '&guid=4441071008&uin=0&fromtag=66') # 下载接口
except:
print("检测到异常,请重新下载")
break
print("*"*30)
for m in range(0, len(src)):
print("%-4d" % (int(m+1)) + '《' + song_names[m] + '》' + ' - ' + singers[m])
song_index = int(input("请选择序号:").strip())
if song_index < 0:
print("退出QQ音乐爬虫程序")
break
try:
song_data = self.get_request(src[song_index - 1])
data = song_data.content
self.download(data, song_names[song_index-1])
except Exception as er:
print("检测到异常,请重新下载 ", er)