-
Notifications
You must be signed in to change notification settings - Fork 283
Expand file tree
/
Copy path虾米.js
More file actions
164 lines (148 loc) · 6.16 KB
/
虾米.js
File metadata and controls
164 lines (148 loc) · 6.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/**
* 虾米视频解析器
*
* 功能描述:
* 这是一个基于虾米解析服务的视频解析器,使用加密通信协议与第三方解析API交互。
* 支持多种视频平台的解析,采用AES加密确保通信安全。
*
* 主要功能:
* 1. 视频链接解析 - 解析各大视频平台的播放链接
* 2. 加密通信 - 使用MD5+AES加密与解析服务通信
* 3. 动态UA - 使用随机User-Agent避免被识别
* 4. 安全解密 - 对返回的加密播放链接进行AES解密
*
* 技术特点:
* - MD5签名验证:对请求参数进行MD5哈希签名
* - AES加密通信:使用AES-CBC模式加密请求数据
* - AES解密响应:解密服务器返回的加密播放链接
* - 随机UA:动态生成User-Agent避免检测
*
* API接口:
* GET /parse/虾米?url={视频页面URL}
*
* 使用示例:
* http://localhost:5757/parse/虾米?url=https://v.qq.com/x/cover/mzc00200vkqr54u/v4100qp69zl.html
*
* 第三方服务:
* - 解析服务:https://122.228.8.29:4433/xmflv.js
* - 参考站点:https://jx.xmflv.com
*
* 加密算法:
* - 签名:MD5(时间戳 + URL编码的视频链接)
* - 加密:AES-CBC模式,ZeroPadding填充
* - 解密:AES-CBC模式,Pkcs7填充
*
* @author drpy-node
* @version 1.0.0
*/
// 示例调用URL:
// http://localhost:5757/parse/虾米?url=https://v.qq.com/x/cover/mzc00200vkqr54u/v4100qp69zl.html
// 参考解析站点:https://jx.xmflv.com/?url=https://v.qq.com/x/cover/mzc00200qon7vo3/b4100sccuyb.html
// 导入HTML请求工具
const {getHtml} = $.require('./_lib.request.js')
/**
* 解析器配置对象
* 定义了请求头信息
*/
const jx = {
header: {
'User-Agent': PC_UA, // 使用PC端User-Agent
'Referer': 'https://jx.xmflv.com' // 设置来源页面,模拟从官方站点访问
},
};
/**
* 懒加载解析函数
* 使用加密通信协议解析视频链接
*
* @param {string} input - 待解析的视频页面URL
* @param {Object} params - 解析参数(当前未使用)
* @returns {Promise<Object>} 包含解密后播放链接和请求头的对象
*
* @example
* const result = await lazy('https://v.qq.com/x/cover/mzc00200vkqr54u/v4100qp69zl.html');
* // 返回: {url: '解密后的播放链接', header: {请求头信息}}
*/
async function lazy(input, params) {
console.log('input:', input);
// 生成时间戳作为请求标识
const t = Date.now()
// 生成MD5签名:MD5(时间戳 + URL编码的视频链接)
const a = CryptoJS.MD5(t + encodeURIComponent(input)).toString()
/**
* AES加密签名函数
* 使用MD5哈希作为密钥,对签名进行AES加密
*
* @param {string} a - 待加密的签名字符串
* @returns {string} AES加密后的字符串
*/
const sign = function (a) {
const b = CryptoJS.MD5(a); // 对签名进行MD5哈希作为密钥
const c = CryptoJS.enc.Utf8.parse(b); // 将MD5结果转换为UTF8格式
const d = CryptoJS.enc.Utf8.parse('3cccf88181408f19'); // 固定的初始化向量(IV)
// 使用AES-CBC模式加密,ZeroPadding填充
return CryptoJS.AES.encrypt(a, c, {
iv: d, // 初始化向量
mode: CryptoJS.mode.CBC, // CBC模式
padding: CryptoJS.pad.ZeroPadding // Zero填充
}).toString()
};
// 生成随机User-Agent避免被识别
let ua = randomUa.generateUa();
// 向解析服务发送POST请求
let reqs = (await getHtml({
url: "https://122.228.8.29:4433/xmflv.js", // 解析服务API地址
method: 'POST', // 使用POST方法
headers: {
'User-Agent': ua, // 随机User-Agent
'Origin': 'https://jx.xmflv.com' // 设置来源域名
},
data: qs.stringify({ // 表单数据
'wap': '', // WAP标识(空)
'url': encodeURIComponent(input), // URL编码的视频链接
'time': t, // 时间戳
'key': sign(a) // 加密签名
}),
})).data;
// 从响应中提取解密所需的参数
let key = reqs.aes_key // AES解密密钥
let iv = reqs.aes_iv // AES解密初始化向量
let play_url = reqs.url // 加密的播放链接
// 注释掉的M3U8处理代码(备用)
// let m3u8 = (await axios.request({
// url:m3u8_url
// })).data
// 返回解密后的播放链接和请求头
return {
url: decrypt(play_url, key, iv), // 解密播放链接
header: {
'origin': 'https://jx.xmflv.cc/', // 设置来源域名
// 'Origin': 'https://jx.xmflv.com', // 备用来源域名(已注释)
'User-Agent': ua, // 使用相同的随机User-Agent
}
}
}
/**
* AES解密函数
* 使用AES-CBC模式解密服务器返回的加密播放链接
*
* @param {string} text - 加密的文本(Base64格式)
* @param {string} aes_key - AES解密密钥
* @param {string} aes_iv - AES解密初始化向量
* @returns {string} 解密后的明文播放链接
*
* @example
* const playUrl = decrypt(encryptedUrl, key, iv);
*/
function decrypt(text, aes_key, aes_iv) {
// 将密钥和IV转换为UTF8格式
let key = CryptoJS.enc.Utf8.parse(aes_key),
iv = CryptoJS.enc.Utf8.parse(aes_iv),
// 使用AES-CBC模式解密,Pkcs7填充
decrypted = CryptoJS.AES.decrypt(text, key, {
iv: iv, // 初始化向量
mode: CryptoJS.mode.CBC, // CBC模式
padding: CryptoJS.pad.Pkcs7 // Pkcs7填充
});
// 将解密结果转换为UTF8字符串并返回
return decrypted.toString(CryptoJS.enc.Utf8);
}