以QQ音乐的单曲页面URL https://y.qq.com/n/yqq/song/000YU69H3N55rZ.html 为例,说明如何解析得到真实的音频地址。
打开该页面地址,是这样的:
梦一场 - 那英 - QQ音乐
点击页面中的播放按钮,会在新页面的播放器里播放该音乐。在新页面中打开开发者工具的网络探测,重新刷新页面,会发现相关请求如下:
https://c.y.qq.com/base/fcgi-bin/fcg_music_express_mobile3.fcg?g_tk=5381&jsonpCallback=MusicJsonCallback39355320624659207&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8¬ice=0&platform=yqq&needNewCode=0&cid=205361747&callback=MusicJsonCallback39355320624659207&uin=0&songmid=000YU69H3N55rZ&filename=C400000YU69H3N55rZ.m4a&guid=328569683
http://dl.stream.qqmusic.qq.com/C400000YU69H3N55rZ.m4a?vkey=927C721D272189FED484EF874A8D646C6B13C20C53277FB99D496DA6804CDF1B64C33A4F049D24FFC4366605DB4755A6E9AB632AA770C09A&guid=328569683&uin=0&fromtag=66
其中,第二个请求就是音频的真实地址,该地址中主要有如下几个部分:
第一个请求的响应如下:
MusicJsonCallback39355320624659207({"code":0,"cid":205361747,"data":{"expiration":80400,"items":[{"subcode":0,"songmid":"000YU69H3N55rZ","filename":"C400000YU69H3N55rZ.m4a","vkey":"927C721D272189FED484EF874A8D646C6B13C20C53277FB99D496DA6804CDF1B64C33A4F049D24FFC4366605DB4755A6E9AB632AA770C09A"}]}})
我们发现,vkey参数值就在上述响应内容里面。songmid的值正好出现在单曲页面URL里面,通过字符串拼接可以得到文件名:"C400" + songmid + ".m4a"
只有文件名和vkey是不够的,还需要知道guid参数值是如何得来的,没有guid参数的话请求音频真实地址会返回响应码403。
在js文件 https://y.gtimg.cn/music/portal/js/common/pkg/player_module_b5739d0.js 中,搜索 fcg_music_express_mobile3 可找到如下jsonp请求代码:
r.length > 0 ? MUSIC.jQueryAjax.jsonp({
url: location.protocol + "//c.y.qq.com/base/fcgi-bin/fcg_music_express_mobile3.fcg",
data: {
cid: 205361747,
format: "json",
callback: a,
uin: g_user.getUin(),
songmid: r.join(","),
filename: n.join(","),
guid: _getGuid()
},
...
}) : t && t()
这段js代码正好写明了请求参数有哪些,guid是通过调用 _getGuid 得到的。_getGuid 方法的代码如下:
function _getGuid() {
if (_guid.length > 0)
return _guid;
var e = MUSIC.cookie.get("pgv_pvid");
if (e && e.length > 0)
return _guid = e;
var t = (new Date).getUTCMilliseconds();
return _guid = Math.round(2147483647 * Math.random()) * t % 1e10,
document.cookie = "pgv_pvid=" + _guid + "; Expires=Sun, 18 Jan 2038 00:00:00 GMT; PATH=/; DOMAIN=qq.com;",
_guid
}
由此可见,guid的核心构造代码是如下两行:
var t = (new Date).getUTCMilliseconds()
_guid = Math.round(2147483647 * Math.random()) * t % 1e10
import re
import json
import time
import random
import requests
def resolve(url):
"""
resolve audio url
:param url: like 'https://y.qq.com/n/yqq/song/000YU69H3N55rZ.html'
:return:
"""
songmid = re.search('/(\w+).html$', url).groups()[0]
filename = 'C400' + songmid + '.m4a'
guid = int(random.random() * 2147483647) * int(time.time() * 1000) % 10000000000
d = {
'format': 'json',
'cid': 205361747,
'uin': 0,
'songmid': songmid,
'filename': filename,
'guid': guid,
}
r = requests.get('https://c.y.qq.com/base/fcgi-bin/fcg_music_express_mobile3.fcg', params=d, verify=False)
vkey = json.loads(r.content)['data']['items'][0]['vkey']
audio_url = 'http://dl.stream.qqmusic.qq.com/%s?vkey=%s&guid=%s&uin=0&fromtag=66' % (filename, vkey, guid)
return audio_url
附上:http://dl.stream.qqmusic.qq.com/C400004DXFlC0nsTCZ.m4a?vkey=AB2D2F5D31455D28C217B141D074AB5DCB5F0C6CF424361C46CDF8E977497C5C3030678C4D933F587617C0CA2EE4786FB5FA6551DAF65C0A&guid=9008140148&uin=0&fromtag=66
这个为李荣浩的年少有为的真实url地址
转自:https://www.jianshu.com/p/b26c0c9c6149