虽然网易云有外链,但是外链并不能直接获取vip歌曲
外链地址
http://music.163.com/song/media/outer/url?id=xxx.mp3
比如这首歌不需要VIP就可以直接解析
但是下面这个就不行了
就算是登录了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/
分别是哔哩哔哩序号35,小米运动序号2,米友社序号13,这个是同一个账号下运行的任务