QQ音乐的歌曲真实地址解析

以QQ音乐的单曲页面URL https://y.qq.com/n/yqq/song/000YU69H3N55rZ.html 为例,说明如何解析得到真实的音频地址。

打开该页面地址,是这样的:

QQ音乐的歌曲真实地址解析_第1张图片
梦一场 - 那英 - 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

其中,第二个请求就是音频的真实地址,该地址中主要有如下几个部分:

  • 文件名: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

Python代码示例

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

你可能感兴趣的:(QQ音乐的歌曲真实地址解析)