使用网易云API获取歌曲ID对应的播放链接

虽然网易云有外链,但是外链并不能直接获取vip歌曲

外链地址

http://music.163.com/song/media/outer/url?id=xxx.mp3
比如这首歌不需要VIP就可以直接解析

http://music.163.com/song/media/outer/url?id=1818031620.mp3


但是下面这个就不行了

http://music.163.com/song/media/outer/url?id=86369.mp3


就算是登录了vip账号也不能解析

最近写一个QQ机器人的点歌服务,就想着能不能解析VIP歌曲在群里分享,因此找出了一个很早之前下的python脚本,也不知道出处在哪里,反正网上似乎找不到了,然后试了一下,居然能用,由于机器人是java服务,不想直接调用python,就改写成了java代码
下面是两种源码

python源码

# -*- coding: GBK -*-
import scrapy
import time
import random
import math
from Crypto.Cipher import AES
import codecs
import base64
import requests
from lxml import etree
import json

niubi = "1392942840"
cookie = ""


class niub:
    def __init__(self):
        self.key = '0CoJUm6Qyw8W8jud'
        self.f = '00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7'
        self.e = '010001'
        self.singer_id = '1411492497'
        self.post_url1 = 'https://music.163.com/weapi/user/getfolloweds?csrf_token='
        self.post_url2 = 'https://music.163.com/weapi/v1/play/record?csrf_token='

    def _generate_random_strs(self, length):
        string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
        i = 0
        random_strs = ""
        while i < length:
            e = random.random() * len(string)
            e = math.floor(e)
            random_strs = random_strs + list(string)[e]
            i = i + 1
        return random_strs

    def _AESencrypt(self, msg, key):
        padding = 16 - len(msg) % 16
        msg = msg + padding * chr(padding)
        iv = '0102030405060708'
        Cipher = AES.new(key.encode('utf-8'), AES.MODE_CBC, iv.encode('utf-8'))
        encryptedbytes = Cipher.encrypt(msg.encode('utf8'))
        encodestrs = base64.b64encode(encryptedbytes)
        enctext = encodestrs.decode('utf-8')
        return enctext

    def _RSAencrypt(self, randomstrs, key, f):
        string = randomstrs[::-1]
        text = bytes(string, 'utf-8')
        seckey = int(codecs.encode(text, encoding='hex'), 16) ** int(key, 16) % int(f, 16)
        return format(seckey, 'x').zfill(256)

    def _get_params1(self, mingzi1):
        msg = '{ids: "[%s]", level: "standard", encodeType: "aac", csrf_token: ""}' % str(mingzi1)
        enctext = self._AESencrypt(msg, self.key)
        i = self._generate_random_strs(16)
        encText = self._AESencrypt(enctext, i)
        print(encText)
        encSecKey = self._RSAencrypt(i, self.e, self.f)
        print(encSecKey)
        return encText, encSecKey


#     def start_requests(self):
#         params, encSecKey = self._get_params1(i)
#         formdata = {
#             'params': params, 'encSecKey': encSecKey
#         }
#         yield formdata
# msg = '{"userId": "1411492497", "offset":"1", "total": "false", "limit": "20", "csrf_token": ""}'
# key = '0CoJUm6Qyw8W8jud'

def lianjie(mingzi):
    x = niub()
    data1 = x._get_params1(mingzi)
    a = data1[0]
    b = data1[1]
    headers = {'Host': 'music.163.com',
               'Connection': 'keep-alive',
               'Content-Length': '476',
               'Pragma': 'no-cache',
               'Cache-Control': 'no-cache',
               'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36',
               'Content-Type': 'application/x-www-form-urlencoded',
               'Accept': '*/*',
               'Origin': 'https://music.163.com',
               'Sec-Fetch-Site': 'same-origin',
               'Sec-Fetch-Mode': 'cors',
               'Sec-Fetch-Dest': 'empty',
               'Referer': 'https://music.163.com/user/fans?id=1411492497',
               'Accept-Encoding': 'gzip, deflate, br',
               'Accept-Language': 'zh-CN,zh;q=0.9',
               }
    headers["cookie"] = cookie
    url = 'https://music.163.com/weapi/song/enhance/player/url/v1?csrf_token='
    data = {
        'params': a,
        'encSecKey': b,
    }
    r = requests.post(url=url, data=data, headers=headers, verify=False)
    return r


def writeInfomation(contont):
    for user in json.loads(contont.text)['data']:
        mingzi = user['id']
        dizhi = user['url']
        if dizhi == None:
            print("error歌曲链接获取失败!")
            return
        br = user['br']
        mingzi = str(mingzi) + '_' + str(br)
        url = dizhi
        print(mingzi)
        print('#url' + url + 'url#')


def main(niubi):
    # lianjie(niubi)
    zuihou = lianjie(niubi)
    writeInfomation(zuihou)


main(niubi)

原作者写的挺乱,有不少没用的东西,部分我已经注释了,其余看着改,反正填入cookie就能用

java代码

不太熟悉python,百度了一个下午

    private static final String key = "0CoJUm6Qyw8W8jud";
    private static final String f = "00e0b509f6259df8642dbc35662901477df22677ec152b5ff68ace615bb7b725152b3ab17a876aea8a5aa76d2e417629ec4ee341f56135fccf695280104e0312ecbda92557c93870114af6c9d05c4f7f0c3685b7a46bee255932575cce10b424d813cfe4875d3e82047b97ddef52741d546b8e289dc6935b3ece0462db0a22b8e7";
    private static final String e = "010001";
    private static final String cookie = " ";
    private static final String url = "https://music.163.com/weapi/song/enhance/player/url/v1?csrf_token=";
     public static void main(String[] args) {
//5238992测试
//        String playUrl = getPlayUrl("5238992");
//        System.out.println(playUrl);
     }

/**
     * 根据id获取播放链接
     * @param musicId
     * @return
     */
    public static String getPlayUrl(String musicId) {
        JSONObject connect = connect(musicId, cookie);
        if (connect == null) {
            return null;
        }
        JSONArray data = connect.getJSONArray("data");
        JSONObject jsonObject = data.getJSONObject(0);
        return jsonObject.getString("url");
    }


    public static String aESencrypt(String msg, String key) {
        int padding = 16 - msg.length() % 16;
        char ch = (char) (padding);
        for (int i = 0; i < padding; i++) {
            msg = msg + ch;
        }
        String ivParameter = "0102030405060708";
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            byte[] raw = key.getBytes();
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes());//使用CBC模式,需要一个向量iv,可增加加密算法的强度
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
            byte[] encrypted = cipher.doFinal(msg.getBytes(StandardCharsets.UTF_8));
            String base64 = new BASE64Encoder().encode(encrypted);//此处使用BASE64做转码。
            base64 = base64.replaceAll("\r", "");
            base64 = base64.replaceAll("\n", "");
            return base64;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String rSAencrypt(String randomStrs, String key, String f) {
        StringBuilder stringBuilder = new StringBuilder(randomStrs);
        randomStrs = stringBuilder.reverse().toString();
        byte[] text = randomStrs.getBytes(StandardCharsets.UTF_8);
        BigInteger i1 = new BigInteger(byteToHex(text), 16);
        int i2 = Integer.parseInt(key, 16);
        BigInteger i3 = new BigInteger(f, 16);
        BigInteger j = i1.pow(i2);
        BigInteger seckey = j.mod(i3);
        String s = seckey.toString(16);
        return String.format(s, 256);
    }

    public static Map<String, String> getParam1(String mingzi1) {
        String msg = "{ids: \"[" + mingzi1 + "]\", level: \"standard\", encodeType: \"mp3\", csrf_token: \"\"}";
        String enctext = aESencrypt(msg, key);
        String i = NumberUtil.generateRandomStrs(16);
        String encText = aESencrypt(enctext, i);
        String encSecKey = rSAencrypt(i, e, f);
        Map<String, String> map = new HashMap<>();
        map.put("encText", encText);
        map.put("encSecKey", encSecKey);
        return map;
    }

    public static JSONObject connect(String mingzi, String cookie) {
        Map<String, String> param1 = getParam1(mingzi);
        Map<String, String> headers = new HashMap<>();
        Map<String, String> map = new HashMap<>();
        headers.put("Host", "music.163.com");
        headers.put("Connection", "keep-alive");
        headers.put("Pragma", "no-cache");
        headers.put("Cache-Control", "no-cache");
        headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36");
        headers.put("Content-Type", "application/x-www-form-urlencoded");
        headers.put("Accept", "*/*");
        headers.put("Origin", "https://music.163.com");
        headers.put("Sec-Fetch-Site", "same-origin");
        headers.put("Sec-Fetch-Mode", "cors");
        headers.put("Sec-Fetch-Dest", "empty");
        headers.put("Referer", "https://music.163.com/user/fans?id=1411492497");
        headers.put("Accept-Encoding", "gzip, deflate, br");
        headers.put("Accept-Language", "zh-CN,zh;q=0.9");
        headers.put("cookie", cookie);
        map.put("params", param1.get("encText"));
        map.put("encSecKey", param1.get("encSecKey"));
        try {
            HttpResponse httpResponse = HttpUtils.doPost(url, null, headers, null, map);
            return HttpUtils.getJson(httpResponse);
        } catch (Exception exception) {
            exception.printStackTrace();
        }

        return null;
    }


    /**
     * byte数组转hex
     *
     * @param bytes
     * @return
     */
    public static String byteToHex(byte[] bytes) {
        String strHex = "";
        StringBuilder sb = new StringBuilder();
        for (int n = 0; n < bytes.length; n++) {
            strHex = Integer.toHexString(bytes[n] & 0xFF);
            sb.append((strHex.length() == 1) ? "0" + strHex : strHex); // 每个字节由两个字符表示,位数不够,高位补0
        }
        return sb.toString().trim();
    }


    /**
     * 生成随机字符串
     * @param length
     * @return
     */
    public static String generateRandomStrs(int length) {
        String string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        int i = 0;
        String randomStrs = "";
        while (i < length) {
            Random random = new Random();
            double e = random.nextDouble() * string.length();
            e = Math.floor(e);
            randomStrs = randomStrs + string.toCharArray()[(int) e];
            i++;
        }
        return randomStrs;
    }

HttpUtils见这篇文章:https://blog.oldwu.top/index.php/archives/69/

评论区
头像
文章目录