js逆向实战(1)-- 某☁️音乐下载

下载某云音乐源文件.mp4格式

首先随便点进一首歌,如图所示获取该音乐id,然后点击播放键,打开F12进行查询XHR

由此可知,实际请求网址是

https://music.163.com/weapi/song/enhance/player/url/v1?csrf_token=「你的token」

url需带上token,请求参数有两个:params、encSecKey

返回json里的id就是该音乐id,url就是本次的目标音乐源文件链接

继续查看启动器,查看该路由的调用堆栈信息,找到关键位置打断点,不会找断点的就每个堆栈全部点进去设置断点,然后看哪一个断点结束后url已完成请求的就是关键位置,从下图的文件中可知,核心文件是core_xxxxx.js,可以直接下载到本地方便查看代码。(堆栈执行顺序是由下至上)

第一步,已成功定位到请求路由,e7d.data里已经带有(params、encSecKey),后续就直接会请求了,那么就继续向上一个堆栈找此函数的参数(x7q,e7d)中的e7d是从哪里传的。

PS:请注意,一定要找到我们要找的核心url是否由此断点发出的,由于一些方法会被反复调用,参数值是不一定的。

第二步,上图已封装好了e7d,且参数params、encSecKey已出现,是由window.asrsea产生的,继续查找window.asrsea是哪个方法。

window.asrsea(JSON.stringify(i7b), bsc2x(["流泪", "强"]), bsc2x(RU7N.md), bsc2x(["爱心", "女孩", "惊恐", "大笑"]));

鼠标悬浮该方法后定位至这里,核心就是这个function d,接受4个参数,分别对应上面的4个值。

其中第一个参数i7b是以下参数构成

music_id = XXXXXX
song_data = {
    "ids": f"[{music_id}]",
    "level": "standard",
    "encodeType": "aac",
    "csrf_token": csrf_token
}

第三个参数md是一个固定列表,第二、第四个参数也是一个短列表值。

核心方法已找到,就是function d(),剩下的工作就是把d方法里需要涉及到的所有function全部找出来,比如function b、c,然后继续从b、c里继续递归找方法,这一步工作比较繁琐需要耐心。直至自己用js能把function d给跑通就算成功。

通过js里的方法可知,里面算法还涉及到了加密,需要用到crypto-js库,上网百度搜一下直接下载该库的代码保存本地。

以下是js文件代码:


    var CryptoJS = require('./package/crypto-js.js');

    var bd7W = {};
    var maxDigits,
    ZERO_ARRAY,
    bigZero,
    bigOne,
    dpl10,
    lr10,
    hexatrigesimalToChar,
    hexToChar,
    highBitMasks,
    lowBitMasks,
    biRadixBase = 2,
    biRadixBits = 16,
    bitsPerDigit = biRadixBits,
    biRadix = 65536,
    biHalfRadix = biRadix >>> 1,
    biRadixSquared = biRadix * biRadix,
    maxDigitVal = biRadix - 1,
    maxInteger = 9999999999999998;
    setMaxDigits(20),
    dpl10 = 15,
    lr10 = biFromNumber(1e15),
    hexatrigesimalToChar = new Array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"),
    hexToChar = new Array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"),
    highBitMasks = new Array(0, 32768, 49152, 57344, 61440, 63488, 64512, 65024, 65280, 65408, 65472, 65504, 65520, 65528, 65532, 65534, 65535),
    lowBitMasks = new Array(0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535);



    function encryptedString(a, b) {

    for (var f, g, h, i, j, k, l, c = new Array, d = b.length, e = 0; d > e;)
        c[e] = b.charCodeAt(e),
        e++;
    for (; 0 != c.length % a.chunkSize;)
        c[e++] = 0;
    for (f = c.length, g = "", e = 0; f > e; e += a.chunkSize) {
        for (j = new BigInt, h = 0, i = e; i < e + a.chunkSize; ++h)
            j.digits[h] = c[i++],
            j.digits[h] += c[i++] << 8;
        k = a.barrett.powMod(j, a.e),
        l = 16 == a.radix ? biToHex(k) : biToString(k, a.radix),
        g += l + " "
    }
    return g.substring(0, g.length - 1)
}
    function biSubtract(a, b) {
    var c,
        d,
        e,
        f;
    if (a.isNeg != b.isNeg)
        b.isNeg = !b.isNeg,
        c = biAdd(a, b),
        b.isNeg = !b.isNeg;
    else {
        for (c = new BigInt, e = 0, f = 0; f < a.digits.length; ++f)
            d = a.digits[f] - b.digits[f] + e,
            c.digits[f] = 65535 & d,
            c.digits[f] < 0 && (c.digits[f] += biRadix),
            e = 0 - Number(0 > d);
        if (-1 == e) {
            for (e = 0, f = 0; f < a.digits.length; ++f)
                d = 0 - c.digits[f] + e,
                c.digits[f] = 65535 & d,
                c.digits[f] < 0 && (c.digits[f] += biRadix),
                e = 0 - Number(0 > d);
            c.isNeg = !a.isNeg
        } else
            c.isNeg = a.isNeg
    }
    return c
}
    function biCompare(a, b) {
        if (a.isNeg != b.isNeg)
            return 1 - 2 * Number(a.isNeg);
        for (var c = a.digits.length - 1; c >= 0; --c)
            if (a.digits[c] != b.digits[c])
                return a.isNeg ? 1 - 2 * Number(a.digits[c] > b.digits[c]) : 1 - 2 * Number(a.digits[c] < b.digits[c]);
        return 0
    }
    function biMultiplyByRadixPower(a, b) {
        var c = new BigInt;
        return arrayCopy(a.digits, 0, c.digits, b, c.digits.length - b), c
    }
    function arrayCopy(a, b, c, d, e) {
        var g,
            h,
            f = Math.min(b + e, a.length);
        for (g = b, h = d; f > g; ++g, ++h)
            c[h] = a[g]
    }

    function biShiftLeft(a, b) {
        var e,
            f,
            g,
            h,
            c = Math.floor(b / bitsPerDigit),
            d = new BigInt;
        for (arrayCopy(a.digits, 0, d.digits, c, d.digits.length - c), e = b % bitsPerDigit, f = bitsPerDigit - e, g = d.digits.length - 1, h = g - 1; g > 0; --g, --h)
            d.digits[g] = d.digits[g] << e & maxDigitVal | (d.digits[h] & highBitMasks[e]) >>> f;
        return d.digits[0] = d.digits[g] << e & maxDigitVal, d.isNeg = a.isNeg, d
    }
    function biFromNumber(a) {
        var c,
            b = new BigInt;
        for (b.isNeg = 0 > a, a = Math.abs(a), c = 0; a > 0;)
            b.digits[c++] = a & maxDigitVal,
            a >>= biRadixBits;
        return b
    }

    function biNumBits(a) {
        var e,
            b = biHighIndex(a),
            c = a.digits[b],
            d = (b + 1) * bitsPerDigit;
        for (e = d; e > d - bitsPerDigit && 0 == (32768 & c); --e)
            c <<= 1;
        return e
    }

    function biDivideModulo(a, b) {
        var f,
            g,
            h,
            i,
            j,
            k,
            l,
            m,
            n,
            o,
            p,
            q,
            r,
            s,
            c = biNumBits(a),
            d = biNumBits(b),
            e = b.isNeg;
        if (d > c)
            return a.isNeg ? (f = biCopy(bigOne), f.isNeg = !b.isNeg, a.isNeg = !1, b.isNeg = !1, g = biSubtract(b, a), a.isNeg = !0, b.isNeg = e) : (f = new BigInt, g = biCopy(a)), new Array(f, g);
        for (f = new BigInt, g = a, h = Math.ceil(d / bitsPerDigit) - 1, i = 0; b.digits[h] < biHalfRadix;)
            b = biShiftLeft(b, 1),
            ++i,
            ++d,
            h = Math.ceil(d / bitsPerDigit) - 1;
        for (g = biShiftLeft(g, i), c += i, j = Math.ceil(c / bitsPerDigit) - 1, k = biMultiplyByRadixPower(b, j - h); -1 != biCompare(g, k);)
            ++f.digits[j - h],
            g = biSubtract(g, k);
        for (l = j; l > h; --l) {
            for (m = l >= g.digits.length ? 0 : g.digits[l], n = l - 1 >= g.digits.length ? 0 : g.digits[l - 1], o = l - 2 >= g.digits.length ? 0 : g.digits[l - 2], p = h >= b.digits.length ? 0 : b.digits[h], q = h - 1 >= b.digits.length ? 0 : b.digits[h - 1], f.digits[l - h - 1] = m == p ? maxDigitVal : Math.floor((m * biRadix + n) / p), r = f.digits[l - h - 1] * (p * biRadix + q), s = m * biRadixSquared + (n * biRadix + o); r > s;)
                --f.digits[l - h - 1],
                r = f.digits[l - h - 1] * (p * biRadix | q),
                s = m * biRadix * biRadix + (n * biRadix + o);
            k = biMultiplyByRadixPower(b, l - h - 1),
            g = biSubtract(g, biMultiplyDigit(k, f.digits[l - h - 1])),
            g.isNeg && (g = biAdd(g, k), --f.digits[l - h - 1])
        }
        return g = biShiftRight(g, i), f.isNeg = a.isNeg != e, a.isNeg && (f = e ? biAdd(f, bigOne) : biSubtract(f, bigOne), b = biShiftRight(b, i), g = biSubtract(b, g)), 0 == g.digits[0] && 0 == biHighIndex(g) && (g.isNeg = !1), new Array(f, g)
    }
    function BarrettMu_modulo(a) {
        var i,
            b = biDivideByRadixPower(a, this.k - 1),
            c = biMultiply(b, this.mu),
            d = biDivideByRadixPower(c, this.k + 1),
            e = biModuloByRadixPower(a, this.k + 1),
            f = biMultiply(d, this.modulus),
            g = biModuloByRadixPower(f, this.k + 1),
            h = biSubtract(e, g);
        for (h.isNeg && (h = biAdd(h, this.bkplus1)), i = biCompare(h, this.modulus) >= 0; i;)
            h = biSubtract(h, this.modulus),
            i = biCompare(h, this.modulus) >= 0;
        return h
    }
    function BarrettMu_multiplyMod(a, b) {
        var c = biMultiply(a, b);
        return this.modulo(c)
    }
    function biDivideByRadixPower(a, b) {
        var c = new BigInt;
        return arrayCopy(a.digits, b, c.digits, 0, c.digits.length - b), c
    }
    function reverseStr(a) {
        var c,
            b = "";
        for (c = a.length - 1; c > -1; --c)
            b += a.charAt(c);
        return b
    }
    function digitToHex(a) {
        var b = 15,
            c = "";
        for (i = 0; 4 > i; ++i)
            c += hexToChar[a & b],
            a >>>= 4;
        return reverseStr(c)
    }
    function biToHex(a) {
        var d,
            b = "";
        for (biHighIndex(a), d = biHighIndex(a); d > -1; --d)
            b += digitToHex(a.digits[d]);
        return b
    }
    function biModuloByRadixPower(a, b) {
        var c = new BigInt;
        return arrayCopy(a.digits, 0, c.digits, 0, b), c
    }
    function biCompare(a, b) {
        if (a.isNeg != b.isNeg)
            return 1 - 2 * Number(a.isNeg);
        for (var c = a.digits.length - 1; c >= 0; --c)
            if (a.digits[c] != b.digits[c])
                return a.isNeg ? 1 - 2 * Number(a.digits[c] > b.digits[c]) : 1 - 2 * Number(a.digits[c] < b.digits[c]);
        return 0
    }
    function biMultiply(a, b) {
        var d,
            h,
            i,
            k,
            c = new BigInt,
            e = biHighIndex(a),
            f = biHighIndex(b);
        for (k = 0; f >= k; ++k) {
            for (d = 0, i = k, j = 0; e >= j; ++j, ++i)
                h = c.digits[i] + a.digits[j] * b.digits[k] + d,
                c.digits[i] = h & maxDigitVal,
                d = h >>> biRadixBits;
            c.digits[k + e + 1] = d
        }
        return c.isNeg = a.isNeg != b.isNeg, c
    }
    function BarrettMu_powMod(a, b) {
        var d,
            e,
            c = new BigInt;
        for (c.digits[0] = 1, d = a, e = b;;) {
            if (0 != (1 & e.digits[0]) && (c = this.multiplyMod(c, d)), e = biShiftRight(e, 1), 0 == e.digits[0] && 0 == biHighIndex(e))
                break;
            d = this.multiplyMod(d, d)
        }
        return c
    }
    function biShiftRight(a, b) {
        var e,
            f,
            g,
            h,
            c = Math.floor(b / bitsPerDigit),
            d = new BigInt;
        for (arrayCopy(a.digits, c, d.digits, 0, a.digits.length - c), e = b % bitsPerDigit, f = bitsPerDigit - e, g = 0, h = g + 1; g < d.digits.length - 1; ++g, ++h)
            d.digits[g] = d.digits[g] >>> e | (d.digits[h] & lowBitMasks[e]) << f;
        return d.digits[d.digits.length - 1] >>>= e, d.isNeg = a.isNeg, d
    }
    function biMultiplyDigit(a, b) {
        var c,
            d,
            e,
            f;
        for (result = new BigInt, c = biHighIndex(a), d = 0, f = 0; c >= f; ++f)
            e = result.digits[f] + a.digits[f] * b + d,
            result.digits[f] = e & maxDigitVal,
            d = e >>> biRadixBits;
        return result.digits[1 + c] = d, result
    }
    function biDivide(a, b) {
        return biDivideModulo(a, b)[0]
    }
    function biCopy(a) {
        var b = new BigInt(!0);
        return b.digits = a.digits.slice(0), b.isNeg = a.isNeg, b
    }
    function BarrettMu(a) {
        this.modulus = biCopy(a),
        this.k = biHighIndex(this.modulus) + 1;
        var b = new BigInt;
        b.digits[2 * this.k] = 1,
        this.mu = biDivide(b, this.modulus),
        this.bkplus1 = new BigInt,
        this.bkplus1.digits[this.k + 1] = 1,
        this.modulo = BarrettMu_modulo,
        this.multiplyMod = BarrettMu_multiplyMod,
        this.powMod = BarrettMu_powMod
    }

    function BigInt(a) {
        this.digits = "boolean" == typeof a && 1 == a ? null : ZERO_ARRAY.slice(0),
        this.isNeg = !1
    }
    function charToHex(a) {
        var h,
            b = 48,
            c = b + 9,
            d = 97,
            e = d + 25,
            f = 65,
            g = 90;
        return h = a >= b && c >= a ? a - b : a >= f && g >= a ? 10 + a - f : a >= d && e >= a ? 10 + a - d : 0
    }
    function hexToDigit(a) {
    var d,
        b = 0,
        c = Math.min(a.length, 4);
    for (d = 0; c > d; ++d)
        b <<= 4,
        b |= charToHex(a.charCodeAt(d));
    return b
}
    function biFromHex(a) {
        var d,
            e,
            b = new BigInt,
            c = a.length;
        for (d = c, e = 0; d > 0; d -= 4, ++e)
            b.digits[e] = hexToDigit(a.substr(Math.max(d - 4, 0), Math.min(d, 4)));
        return b
    }

    function RSAKeyPair(a, b, c) {
        this.e = biFromHex(a),
        this.d = biFromHex(b),
        this.m = biFromHex(c),
        this.chunkSize = 2 * biHighIndex(this.m),
        this.radix = 16,
        this.barrett = new BarrettMu(this.m)
    }

    function biHighIndex(a) {
        for (var b = a.digits.length - 1; b > 0 && 0 == a.digits[b];)
            --b;
        return b
    }

    function setMaxDigits(a) {
        maxDigits = a,
        ZERO_ARRAY = new Array(maxDigits);
        for (var b = 0; b < ZERO_ARRAY.length; b++)

            ZERO_ARRAY[b] = 0;
        bigZero = new BigInt,
        bigOne = new BigInt,
        bigOne.digits[0] = 1
    }

    var Hb6V = function(i7b, u7n) {
        try {
            u7n = u7n.toLowerCase();
            if (i7b === null)
                return u7n == "null";
            if (i7b === undefined)
                return u7n == "undefined";
            return bd7W.toString.call(i7b).toLowerCase() == "[object " + u7n + "]"
        } catch (e) {
            console.log(e)
            return !1
        }
    };


     var md = ["色", "流感", "这边", "弱", "嘴唇", "亲", "开心", "呲牙", "憨笑", "猫", "皱眉", "幽灵", "蛋糕", "发怒", "大哭", "兔子", "星星", "钟情", "牵手", "公鸡", "爱意", "禁止", "狗", "亲亲", "叉", "礼物", "晕", "呆", "生病", "钻石", "拜", "怒", "示爱", "汗", "小鸡", "痛苦", "撇嘴", "惶恐", "口罩", "吐舌", "心碎", "生气", "可爱", "鬼脸", "跳舞", "男孩", "奸笑", "猪", "圈", "便便", "外星", "圣诞"]
     var emj =  {
        "色": "00e0b",
        "流感": "509f6",
        "这边": "259df",
        "弱": "8642d",
        "嘴唇": "bc356",
        "亲": "62901",
        "开心": "477df",
        "呲牙": "22677",
        "憨笑": "ec152",
        "猫": "b5ff6",
        "皱眉": "8ace6",
        "幽灵": "15bb7",
        "蛋糕": "b7251",
        "发怒": "52b3a",
        "大哭": "b17a8",
        "兔子": "76aea",
        "星星": "8a5aa",
        "钟情": "76d2e",
        "牵手": "41762",
        "公鸡": "9ec4e",
        "爱意": "e341f",
        "禁止": "56135",
        "狗": "fccf6",
        "亲亲": "95280",
        "叉": "104e0",
        "礼物": "312ec",
        "晕": "bda92",
        "呆": "557c9",
        "生病": "38701",
        "钻石": "14af6",
        "拜": "c9d05",
        "怒": "c4f7f",
        "示爱": "0c368",
        "汗": "5b7a4",
        "小鸡": "6bee2",
        "痛苦": "55932",
        "撇嘴": "575cc",
        "惶恐": "e10b4",
        "口罩": "24d81",
        "吐舌": "3cfe4",
        "心碎": "875d3",
        "生气": "e8204",
        "可爱": "7b97d",
        "鬼脸": "def52",
        "跳舞": "741d5",
        "男孩": "46b8e",
        "奸笑": "289dc",
        "猪": "6935b",
        "圈": "3ece0",
        "便便": "462db",
        "外星": "0a22b",
        "圣诞": "8e7",
        "流泪": "01000",
        "强": "1",
        "爱心": "0CoJU",
        "女孩": "m6Qyw",
        "惊恐": "8W8ju",
        "大笑": "d"
    }




    var gO9F =  function(i7b) {

        return Hb6V(i7b, "function")
    }
    var bh7a =  function(k7d, cH8z, O7H) {

        if (!k7d || !k7d.length || !gO9F(cH8z))

            return this;

        if (!!k7d.forEach) {
            k7d.forEach(cH8z, O7H);
            return this
        }

        for (var i = 0, l = k7d.length; i < l; i++)
            cH8z.call(O7H, k7d[i], i, k7d);
        return this
    }


    var bsc2x = function(cya8S) {

        var m7f = [];
        bh7a(cya8S, function(cxZ8R) {
            m7f.push(emj[cxZ8R])
        });

        return m7f.join("")
    };

    function a(a) {
        var d,
            e,
            b = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",
            c = "";
        for (d = 0; a > d; d += 1)
            e = Math.random() * b.length,
            e = Math.floor(e),
            c += b.charAt(e);
        return c
    }
    function b(a, b) {

        var c = CryptoJS.enc.Utf8.parse(b),
            d = CryptoJS.enc.Utf8.parse("0102030405060708"),
            e = CryptoJS.enc.Utf8.parse(a),
            f = CryptoJS.AES.encrypt(e, c, {
                iv: d,
                mode: CryptoJS.mode.CBC
            });

        return f.toString()
    }
    function c(a, b, c) {
        var d,
            e;

        return setMaxDigits(131), d = new RSAKeyPair(b, "", c), e = encryptedString(d, a)
    }

    function decrypt(d, e, f, g) {
        var h = {}
          , i = a(16);
        return h.encText = b(d, g),
        h.encText = b(h.encText, i),
        h.encSecKey = c(i, e, f),
        h
    }

    function e(a, b, d, e) {
        var f = {};
        return f.encText = c(a + e, b, d), f
    }

    function get_efg(){
            var r = {}
            r.e = bsc2x(["流泪", "强"])
            r.f = bsc2x(md)
            r.g = bsc2x(["爱心", "女孩", "惊恐", "大笑"])
           return r
    }

以下是python部分代码,由于要用到js,需要用到execjs库,自行百度pip install。

import traceback
import json
import requests
import execjs

with open("wangyiyun.js") as f:
    jscode = f.read()
js = execjs.compile(jscode)


csrf_token = "your_token"
url = f"https://music.163.com/weapi/song/enhance/player/url/v1?csrf_token={csrf_token}"

headers = {
    "Accept": "*/*",
    "Host": "music.163.com",
    "Accept-Language": "zh-CN,zh-Hans;q=0.9",
    "Content-Type": "application/x-www-form-urlencoded",
    "Accept-Encoding": "gzip, deflate, br",
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.2 Safari/605.1.15",
    "Referer": "https://music.163.com/",
    "Connection": "keep-alive",
    "Cookie": "ntes_kaola_ad=1; JSESSIONID-WYYY=NNam6ZvnitTQAIxhjcnkVGOJe1CSrnqIOsBnuOzx405%2FJAUSng5IDkYIFo00Xb%2BoUldg8unn3ikRohd8TEg%2F5A9IF0d3vIrPq0ggue%2BD%2FCFTwZBaj%2FfbHOgwt15v2R4uXH8%2FJuMri%2F3zPb%2Bl7TH%2B4XFVYq9BghtkAelO6p5uAC4QQxNh%3A1735613258319; _iuqxldmzr_=32; playerid=96541318; WEVNSM=1.0.0; WM_TID=%2FnYekZpayJFEEEVQRRfHMEPNaHmTqyHZ; MUSIC_U=006C5AF78BF74B16F27E5B57A85731911569EB8ABB9380E9315B54803127FFDF3C459640CCB0E2BDE8425D2EE33764BC1DB30AA186B850E1CED2B79EF2436E56F8786A63776BFC2243956C5AC987B3A85797BC545993FB84F14E3C4C66EF506A087542A5DE0B218EEA044FDCED41F7037A2EA93679113D60D72EAD7603A7B74BAF1EA4753BF65B585F5130F58CC7711D5EB79F559AD803761591C3D9AB83F967DDFA019B5C6C58BB126197139D1D4BB311DED63FECC8F6651349C211AEE6BB2A772FFCB717C731082DE27A19C5F24FB6A3311D4B585E8FA92DF7D35A41F4FCCA7129B921D0ABA174034FCDB36CAE4BB69011E30F7A7A657B1D74C7DCE0CCEB7B01E6F34CE848E3627CAF9D536C3255A80CF5B8064216064E40C7AD67CDF74EC118D8F2D4B6D4A0031A2969ABF5BB2FC4CFDE6E679AA4CB5609C96901D706E9500E94B86D80E4A6A3065227ED8690F5686FF885DC3BB6F1DA7467CEB7D4D42A10B4; __csrf=ca6ddf56d40cc8a27f331f202fe4b326; gdxidpyhxdE=4xfjyEeg4lc3N%5Ch2d%5Cmuya67isI3pZMPzyE5piBKE4MbnmjX8cO%2BUPnScJ7ZVrK8%2FyENi%2FPm%2FUJ%5C7Jt7%2Fu%5CxVq0KD8x%2Bs2uyBrRX6bcW9sjSWg%5Cw%2F7KNEkKk%5C6Mn6dM0bzaQBt%2F06wgBdKtOe3TuWkbDmcE6EvqXOdSnvvjBjs44kdz0%3A1735610638700; __snaker__id=1FPbd4ulJdEVbVUp; ntes_utid=tid._.m%252BLT1NjmAjZAUkFUAAaSMBOdaWzOWutc._.0; sDeviceId=YD-YPiVIvIe3u5EAxABBUfFxyhoxuMxXPie; WNMCID=scyqtk.1735609723331.01.0; WM_NI=AvJ1%2BaTN%2Bars6kp4BqZR6lew0ErnCxDEjplQcna1dpw2o38u%2BYsJZfwf7oZZx3RYpR1b0M2XDa5vbBs0LlSAcWKBQpCU5WBUbXnW%2BM%2BjOjngWravnIJ5CDCtziN4QsN0MW8%3D; WM_NIKE=9ca17ae2e6ffcda170e2e6eea6fb4089be9ab8f74483eb8ab3c55f928f8e83d769869482b1c73985abb6a5e72af0fea7c3b92a83aa86d2aa6b9892e582f179f6b5c0d5c17b9a8efa8de87df49bbe8fc274889ba691ef5ba1b2afd2e77cb5eea1d4bb7fe987bdabd96eb5baf990d952bced9ebaf35af3be00aeb15488bffb97e14ab1f0848dd24ba18985a3d47c818bfbb8c15fa288a2b8aa47e9b6818bed6d95aeaf97ed438aeb8da5c280bab782d5d4798ef083b8bb37e2a3; _ntes_nnid=0abb01037659f4b4a2020921c96bcfd4,1735609718336; _ntes_nuid=0abb01037659f4b4a2020921c96bcfd4; NMTID=00Ob7X1eXe08UIQIk_Bl7cELz7aKHkAAAGQCjtDIA",
}

# 音乐id
music_id = 2122122972
song_data = {
    "ids": f"[{music_id}]",
    "level": "standard",
    "encodeType": "aac",
    "csrf_token": csrf_token
}

# 获取js运行的结果
try:
    efg_obj = js.call("get_efg")
    res = js.call("decrypt", *(json.dumps(song_data), efg_obj["e"], efg_obj["f"], efg_obj["g"]))
except:
    print(traceback.format_exc())


data = {
    "params": res["encText"],
    "encSecKey": res["encSecKey"],
}

resp = requests.post(url, headers=headers, data=data)

print(resp.status_code)
print(resp.text)

music = requests.get(url=resp.json()["data"][0]["url"])
with open(f"{music_id}.m4a", "wb") as f:
    f.write(music.content)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/949704.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

学习随笔:word2vec在win11 vs2022下编译、测试运行

word2vec 官网word2vec的本质是在自然语言词条数据集与计算机浮点数据集之间建立双射关系。word2vec建立的数据集最厉害的一点是&#xff0c;将自然语言词条数据集内部的推理过程&#xff0c;映射到了计算机浮点数据集内部的数值运算。我个人感觉理解这个数据映射方式是理解AI大…

开源数据集成平台白皮书重磅发布《Apache SeaTunnel 2024用户案例合集》!

2025年新年临近&#xff0c;Apache SeaTunnel 社区用户案例精选&#x1f4d8;也跟大家见面啦&#xff01;在过去的时间里&#xff0c;SeaTunnel 社区持续成长&#xff0c;吸引了众多开发者的关注与支持。 为了致谢一路同行的伙伴&#xff0c;也为了激励更多人加入技术共创&…

Milvus×合邦电力:向量数据库如何提升15%电价预测精度

01. 全球能源市场化改革下的合邦电力 在全球能源转型和市场化改革的大背景下&#xff0c;电力交易市场正逐渐成为优化资源配置、提升系统效率的关键平台。电力交易通过市场化手段&#xff0c;促进了电力资源的有效分配&#xff0c;为电力行业的可持续发展提供了动力。 合邦电力…

Day21补代码随想录_20241231_669.修剪二叉搜索树|108.将有序数组转换为二叉搜索树|538.把二叉搜索树转换为累加树

669.修剪二叉搜索树 题目 【比增加和删除节点难的多】 给你二叉搜索树的根节点 root &#xff0c;同时给定最小边界 low 和最大边界 high。通过修剪二叉搜索树&#xff0c;使得所有节点的值在 [low, high]中。修剪树 不应该 改变保留在树中的元素的相对结构 (即&#xff0c;…

机场安全项目|基于改进 YOLOv8 的机场飞鸟实时目标检测方法

目录 论文信息 背景 摘要 YOLOv8模型结构 模型改进 FFC3 模块 CSPPF 模块 数据集增强策略 实验结果 消融实验 对比实验 结论 论文信息 《科学技术与工程》2024年第24卷第32期刊载了中国民用航空飞行学院空中交通管理学院孔建国, 张向伟, 赵志伟, 梁海军的论文——…

【USRP】教程:在Macos M1(Apple芯片)上安装UHD驱动(最正确的安装方法)

Apple芯片 前言安装Homebrew安装uhd安装gnuradio使用b200mini安装好的路径下载固件后续启动频谱仪功能启动 gnu radio关于博主 前言 请参考本文进行安装&#xff0c;好多人买了Apple芯片的电脑&#xff0c;这种情况下&#xff0c;可以使用UHD吗&#xff1f;答案是肯定的&#…

【C++数据结构——内排序】希尔排序(头歌实践教学平台习题)【合集】

目录&#x1f60b; 任务描述 相关知识 1. 排序算法基础概念 2.插入排序知识 3. 间隔序列&#xff08;增量序列&#xff09;的概念 4. 算法的时间复杂度和空间复杂度分析 5. 代码实现技巧&#xff08;如循环嵌套、索引计算&#xff09; 测试说明 我的通关代码: 测试结…

每天看一个Fortran文件(9)

最后的输出变量是f 这里面调用了一个关键的子程序&#xff0c;spectral_nudging_filter_fft_2d_ncar 这是一个谱逼近的二维快速傅里叶变换过滤的程序。 二维的滤波这个还不是很清楚&#xff0c;找找技术文件看下 超详细易懂FFT&#xff08;快速傅里叶变换&#xff09;及代码…

Centos源码安装MariaDB 基于GTID主从部署(一遍过)

MariaDB安装 安装依赖 yum install cmake ncurses ncurses-devel bison 下载源码 // 下载源码 wget https://downloads.mariadb.org/interstitial/mariadb-10.6.20/source/mariadb-10.6.20.tar.gz // 解压源码 tar xzvf mariadb-10.5.9.tar.gz 编译安装 cmake -DCMAKE_INSTA…

【通俗理解】AI的两次寒冬:从感知机困局到深度学习前夜

AI的两次寒冬&#xff1a;从感知机困局到深度学习前夜 引用&#xff08;中英双语&#xff09; 中文&#xff1a; “第一次AI寒冬&#xff0c;是因为感知机局限性被揭示&#xff0c;让人们失去了对算法可行性的信心。” “第二次AI寒冬&#xff0c;则是因为专家系统的局限性和硬…

数据结构9.3 - 文件基础(C++)

目录 1 打开文件字符读写关闭文件 上图源自&#xff1a;https://blog.csdn.net/LG1259156776/article/details/47035583 1 打开文件 法 1法 2ofstream file(path);ofstream file;file.open(path); #include<bits/stdc.h> using namespace std;int main() {char path[]…

下载ffmpeg执行文件

打开网址&#xff1a;Download FFmpeg 按下面步骤操作 解压文件就可以看到ffmpeg的执行文件了&#xff0c;需要通过命令行进行使用&#xff1a; ffmpeg命令行使用参考&#xff1a; ffmpeg 常用命令-CSDN博客

网络安全抓包

#知识点&#xff1a; 1、抓包技术应用意义 //有些应用或者目标是看不到的&#xff0c;这时候就要进行抓包 2、抓包技术应用对象 //app,小程序 3、抓包技术应用协议 //http&#xff0c;socket 4、抓包技术应用支持 5、封包技术应用意义 总结点&#xff1a;学会不同对象采用…

国产编辑器EverEdit - 两种删除空白行的方法

1 使用技巧&#xff1a;删除空白行 1.1 应用场景 用户在编辑文档时&#xff0c;可能会遇到很多空白行需要删除的情况&#xff0c;比如从网页上拷贝文字&#xff0c;可能就会存在大量的空白行要删除。 1.2 使用方法 1.2.1 方法1&#xff1a; 使用编辑主菜单 选择主菜单编辑 …

可以输入的下拉框(下拉框数据过大,页面卡死)

项目场景&#xff1a; 提示&#xff1a;这里简述项目相关背景&#xff1a; 在项目中&#xff0c;有些下拉框的数据过于庞大&#xff0c;这样页面有时候会卡死&#xff0c;在vue3中常用的组件库element-puls中有个组件可以避免 在项目中&#xff0c;有些需求要求下拉框选择的同…

基于Python的音乐播放器 毕业设计-附源码73733

摘 要 本项目基于Python开发了一款简单而功能强大的音乐播放器。通过该音乐播放器&#xff0c;用户可以轻松管理自己的音乐库&#xff0c;播放喜爱的音乐&#xff0c;并享受音乐带来的愉悦体验。 首先&#xff0c;我们使用Python语言结合相关库开发了这款音乐播放器。利用Tkin…

谷粒商城-高级篇完结-Sleuth+Zipkin 服务链路追踪

1、基本概念和整合 1.1、为什么用 微服务架构是一个分布式架构&#xff0c;它按业务划分服务单元&#xff0c;一个分布式系统往往有很多个服务单元。由于服务单元数量众多&#xff0c;业务的复杂性&#xff0c;如果出现了错误和异常&#xff0c;很难去定位 。主要体现在&#…

ollama+FastAPI部署后端大模型调用接口

ollamaFastAPI部署后端大模型调用接口 记录一下开源大模型的后端调用接口过程 一、ollama下载及运行 1. ollama安装 ollama是一个本地部署开源大模型的软件&#xff0c;可以运行llama、gemma、qwen等国内外开源大模型&#xff0c;也可以部署自己训练的大模型 ollama国内地…

pandas系列----DataFrame简介

DataFrame是Pandas库中最常用的数据结构之一&#xff0c;它是一个类似于二维数组或表格的数据结构。DataFrame由多个列组成&#xff0c;每个列可以是不同的数据类型&#xff08;如整数、浮点数、字符串等&#xff09;。每列都有一个列标签&#xff08;column label&#xff09;…

Unity【Colliders碰撞器】和【Rigibody刚体】的应用——小球反弹效果

目录 Collider 2D 定义&#xff1a; 类型&#xff1a; Rigidbody 2D 定义&#xff1a; 属性和行为&#xff1a; 运动控制&#xff1a; 碰撞检测&#xff1a; 结合使用 实用检测 延伸拓展 1、在Unity中优化Collider 2D和Rigidbody 2D的性能 2、Unity中Collider 2D…