Sync all projects

This commit is contained in:
github-actions[bot]
2026-07-03 14:44:27 +00:00
parent 76739f4491
commit fe482c649e
52 changed files with 23283 additions and 11320 deletions
+1
View File
@@ -14,6 +14,7 @@
{ "name": "豆瓣高分", "url": "&type=movie&tag=豆瓣高分&page_start={{page-1}}" },
{ "name": "华语", "url": "&type=movie&tag=华语&page_start={{page-1}}" },
{ "name": "欧美", "url": "&type=movie&tag=欧美&page_start={{page-1}}" },
{ "name": "情色", "url": "&type=movie&tag=情色&page_start={{page-1}}" },
{ "name": "韩国", "url": "&type=movie&tag=韩国&page_start={{page-1}}" }
],
"list": {
+436
View File
@@ -0,0 +1,436 @@
/*
@header({
searchable: 1,
filterable: 0,
quickSearch: 1,
title: '百度短剧',
lang: 'cat'
})
*/
import { Crypto as CryptoJS } from 'assets://js/lib/cat.js';
let key = '百度短剧';
let siteName = '';
let siteKey = '';
let siteType = 0;
let shuaCache = [];
let UA = "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36";
let clarity_order = {'蓝光': 1, '超清': 2, '标清': 3};
// ==================== URL配置集中管理 ====================
let rule = {
host: 'https://mbd.baidu.com',
detailHost: 'https://sv.baidu.com',
listUrl: '/feedapi/v1/videoserver/playlets/list?service=bdbox',
searchUrl: '/feedapi/v1/videoserver/playlets/search?service=bdbox',
detailUrl: '/haokan/ui-video/playlet/rec/detail?log=vhk&tn=1020970b&ctn=1008350n&blur=1',
playUrl: '/appui/api?cmd=video/relate&log=vhk&tn=1020970b&ctn=1008350n&blur=1',
};
function init(cfg) {
siteName = (cfg.skey?.split('_')[1] || cfg.skey) || (cfg.key?.split('_')[1] || cfg.key) || '未知';
siteKey = cfg.skey;
siteType = cfg.stype;
}
function home(filter) {
let he = ["全部", "新剧", "限时免费", "精选", "独播"];
let ticailist = [
"神医", "连续剧", "都市", "现代言情", "异能", "逆袭", "甜宠", "总裁", "萌宝", "战神", "宫斗宅斗", "神豪",
"虐恋", "闪婚", "玄幻", "穿越重生", "年代", "家庭伦理", "古代言情", "武侠武打", "赘婿", "单元剧", "青春校园",
"历史架空", "王妃", "鉴宝", "科幻", "军旅战争", "种田"
];
let classes = he.map(name => ({
type_id: name,
type_name: name
}));
classes = classes.concat(ticailist.map(name => ({
type_id: name === "全部" ? "全部题材" : name,
type_name: name
})));
return JSON.stringify({
class: classes,
filters: {}
});
}
async function homeVod() {
const categoryResult = await category('新剧', 1, {}, {});
const categoryList = JSON.parse(categoryResult).list;
return JSON.stringify({
list: [
{
vod_id: 'shua',
vod_name: '发现精彩',
vod_pic: 'https://t8.baidu.com/it/u=615012979,225344800&fm=193'
},
...categoryList
]
});
}
/**
* 合并请求函数 - 统一处理 data 和 body,支持 form-urlencoded 和 JSON
*/
async function request(url, options = {}) {
try {
console.log(`${siteName}${options.method || 'GET'} ${url.split('?')[0]}`);
// 准备基础配置
let requestConfig = {
method: options.method || 'GET',
headers: { "User-Agent": UA, ...options.headers }
};
// 获取内容类型
let contentType = requestConfig.headers['Content-Type'] || '';
// 辅助函数:将对象转换为字符串
function stringifyData(data, format) {
if (format.includes('json')) {
return JSON.stringify(data);
} else {
// 默认 form-urlencoded
const parts = [];
for (let key in data) {
let value = data[key];
if (typeof value === 'object' && value !== null) {
value = JSON.stringify(value);
}
parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));
}
return parts.join('&');
}
}
// 处理数据 - 无论 data 还是 body,统一处理
let requestData = options.data || options.body;
if (requestData) {
if (typeof requestData === 'string') {
// 已经是字符串,直接使用
requestConfig.body = requestData;
} else if (typeof requestData === 'object') {
// 对象,根据内容类型转换
if (!contentType) {
// 没有指定内容类型,默认 form-urlencoded
contentType = 'application/x-www-form-urlencoded';
requestConfig.headers['Content-Type'] = contentType;
}
requestConfig.body = stringifyData(requestData, contentType);
}
}
const res = await req(url, requestConfig);
return res.content || '';
} catch (e) {
console.log(`${siteName}】请求失败: ${e.message}`);
return '';
}
}
async function category(tid, pg, filter, extend) {
pg = pg <= 0 ? 1 : pg;
let sub = ["新剧", "限时免费", "精选", "独播"].includes(tid) ? tid : "新剧";
let tcsub = tid === "全部" || tid === "全部题材" ? "" : tid;
let t = Math.floor(Date.now() / 1000);
let version = await md5(t + "v2");
// 直接传对象
let postData = {
'data': {
"data": {
"extRequest": { "flow_tabid": "13" },
"from": "feed",
"page": "channel_video_landing",
"pd": "feed",
"refreshIndex": pg,
"cursor": "",
"theme": "",
"timestamp": t,
"version": version,
"themes": [
{ "kind": "综合", "names": [sub] },
{ "kind": "题材", "names": [tcsub] }
]
}
}
};
let html = await request(`${rule.host}${rule.listUrl}`, {
method: 'POST',
headers: {
"Connection": "Keep-Alive",
'Content-Type': 'application/x-www-form-urlencoded'
},
data: postData // 可以用 data
});
let res = JSON.parse(html);
let items = res.data.items;
let videos = items.map(it => ({
vod_id: it.collId,
vod_name: it.title,
vod_pic: it.img,
vod_remarks: it.updateStatus,
vod_content: it.description
}));
return JSON.stringify({
page: pg,
pagecount: pg + 1,
limit: 20,
total: items.length * (pg + 1),
list: videos
});
}
async function detail(id) {
if (id === 'shua') {
return JSON.stringify({
list: [{
vod_id: 'shua',
vod_name: '发现精彩',
vod_pic: 'https://t8.baidu.com/it/u=615012979,225344800&fm=193',
vod_play_from: '百度短剧',
vod_play_url: '刷刷看$shua',
vod_tag: '[SHUA][JUMP][V]'
}]
});
}
// 也可以用 body
let html = await request(`${rule.detailHost}${rule.detailUrl}`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: { // body 传对象也会自动处理
playlet_id: id,
vid: "undefined"
}
});
let res = JSON.parse(html);
let dthtml = res.data;
let vids = dthtml.vid_list;
let playArr = vids.map((vid, index) => `${index + 1}$${vid}`);
const vod = {
vod_id: id,
vod_name: dthtml.playlet_title,
vod_pic: dthtml.playlet_poster,
vod_content: dthtml.description,
vod_remarks: `${vids.length}集 热度值:${dthtml.hot_value} 集数:${dthtml.episodes_num}`,
vod_director: dthtml.tag_text,
vod_year: dthtml.create_time,
vod_play_from: "百度短剧",
vod_play_url: playArr.join('#')
};
return JSON.stringify({ list: [vod] });
}
async function play(flag, id, flags) {
if (id == 'shua') {
if (shuaCache.length == 0) {
const randomPage = getRnd(1, 20);
const categories = ["新剧", "限时免费", "精选", "独播"];
const randomCate = categories[Math.floor(Math.random() * categories.length)];
const categoryResult = await category(randomCate, randomPage, {}, {});
const res = JSON.parse(categoryResult);
const videos = [];
for (const it of res.list.slice(0, 10)) {
const detailResult = await detail(it.vod_id);
const detailObj = JSON.parse(detailResult);
const vod = detailObj.list[0];
const match = vod.vod_remarks.match(/(\d+)/);
const episodeCount = match[1];
videos.push({
parse: 0,
url: it.vod_id,
shuaTitle: vod.vod_name,
shuaDes: '共' + episodeCount + '集 | ' + vod.vod_content.replace(/\s/g, ''),
shuaActions: { play: it.vod_id },
errorPlayNext: true
});
}
shuaCache.push(...videos);
}
const cache = shuaCache.shift();
const detailResult = await detail(cache.url);
const detailObj = JSON.parse(detailResult);
const vod = detailObj.list[0];
const playUrls = vod.vod_play_url.split('#');
const firstEpisode = playUrls[0];
const vid = firstEpisode.split('$')[1];
const playHtml = await request(`${rule.detailHost}${rule.playUrl}`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: { // 用 data 或 body 都可以
method: "post",
vid: vid
}
});
const playRes = JSON.parse(playHtml);
const playJson = playRes["video/relate"].data.cur_video;
const urls = [];
for (const item of playJson.clarityUrl) {
urls.push({
title: item.title,
url: item.url,
order: clarity_order[item.title] || 999
});
}
urls.sort(function (a, b) { return a.order - b.order; });
cache.url = urls[0].url;
return JSON.stringify(cache);
}
const html = await request(`${rule.detailHost}${rule.playUrl}`, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: { // body 传对象
method: "post",
vid: id
}
});
const res = JSON.parse(html);
const json = res["video/relate"].data.cur_video;
const urls = [];
for (const item of json.clarityUrl) {
urls.push({
title: item.title,
url: item.url,
order: clarity_order[item.title] || 999
});
}
urls.sort(function (a, b) { return a.order - b.order; });
const flat = [];
for (const item of urls) {
flat.push(item.title);
flat.push(item.url);
}
return JSON.stringify({
parse: 0,
url: flat,
header: {
'User-Agent': UA,
'Referer': rule.host
}
});
}
async function search(wd, quick, pg) {
pg = pg <= 0 ? 1 : pg;
let postData = {
'data': {
"data": {
"query": wd,
"page": pg,
"attribute": ["title"],
"fe_page_type": "search",
"extra": {
"tab_id": "216",
"flow_tabid": "13",
"shortplay_source": "feed",
"from": "feed",
"tab_type": "搜索",
"sub_template": "playlet_search_result"
}
}
}
};
let html = await request(`${rule.host}${rule.searchUrl}`, {
method: 'POST',
headers: {
"Connection": "Keep-Alive",
"Accept-Encoding": "gzip",
'Content-Type': 'application/x-www-form-urlencoded'
},
data: postData // 用 data
});
let res = JSON.parse(html);
let items = res.data.itemList;
let videos = items.map(it => ({
vod_id: it.nid.split("_")[1],
vod_name: it.title,
vod_pic: it.img,
vod_remarks: it.collNum + '集',
vod_content: it.description
}));
return JSON.stringify({
page: pg,
pagecount: pg + 1,
limit: 20,
total: items.length * (pg + 1),
list: videos
});
}
function getRnd(min, max, hexNum, isUpper) {
var r = parseInt(Math.random() * (max - min + 1) + min, 10);
if (hexNum) {
r = isUpper ? r.toString(hexNum).toUpperCase() : r.toString(hexNum);
}
return r;
}
async function md5(str) {
return CryptoJS.MD5(str).toString(CryptoJS.enc.Hex).toLowerCase();
}
async function action(action, value) {
if (action === 'shuaPlay') {
return JSON.stringify({
action: {
actionId: '__detail__',
ids: value,
keep: true
}
});
}
}
export function __jsEvalReturn() {
return {
init: init,
home: home,
homeVod: homeVod,
category: category,
detail: detail,
play: play,
search: search,
action: action
};
}
+1729
View File
@@ -0,0 +1,1729 @@
const _0x24a000 = _0x3bf3;
(function (_0x4af1bf, _0x354faf) {
const _0x10067b = _0x3bf3, _0x4787fe = _0x4af1bf();
while (!![]) {
try {
const _0x4356d7 = -parseInt(_0x10067b(0x35d)) / (0x869 * -0x1 + -0x2509 * 0x1 + 0x2d73) * (parseInt(_0x10067b(0x24d)) / (0x112 * 0xe + -0x1d * 0x89 + 0x8b * 0x1)) + -parseInt(_0x10067b(0x3bd)) / (0x3f * -0x5e + 0x1596 + 0x18f) + -parseInt(_0x10067b(0x2f5)) / (0x22aa + -0x255e + -0x57 * -0x8) * (parseInt(_0x10067b(0x1e5)) / (0x1c5d + 0x769 + -0x23c1)) + -parseInt(_0x10067b(0x3c1)) / (0x1 * -0xcff + -0x1e62 + -0x29 * -0x10f) * (parseInt(_0x10067b(0x3ad)) / (0x1b46 * -0x1 + 0xf85 + 0xbc8)) + -parseInt(_0x10067b(0x34a)) / (-0x2576 + -0x1f4d + -0x44cb * -0x1) * (-parseInt(_0x10067b(0x295)) / (-0x2 * 0x7d1 + 0x1 * 0x13d5 + 0x1 * -0x42a)) + parseInt(_0x10067b(0x246)) / (0x43 * 0x59 + -0x2638 + 0x1 * 0xef7) + -parseInt(_0x10067b(0x234)) / (0x2 * 0x11dc + -0x1e02 + 0x1 * -0x5ab) * (-parseInt(_0x10067b(0x21f)) / (0x1 * -0xa75 + 0x119 * 0x15 + -0xc8c));
if (_0x4356d7 === _0x354faf)
break;
else
_0x4787fe['push'](_0x4787fe['shift']());
} catch (_0x531b5c) {
_0x4787fe['push'](_0x4787fe['shift']());
}
}
}(_0x30bd, -0x1 * -0x192eb + -0xa95 * -0x1a7 + -0x7b329));
import {
Crypto,
_
} from 'assets://js/lib/cat.js';
let host = '', header = { 'User-Agent': _0x24a000(0x269) + _0x24a000(0x2e1) }, siteKey = '', siteType = '', siteJx = '';
const urlPattern1 = /api\.php\/.*?\/vod/, urlPattern2 = /api\.php\/.+?\.vod/, parsePattern = /\/.+\\?.+=/, parsePattern1 = /.*(url|v|vid|php\?id)=/, parsePattern2 = /https?:\/\/[^\/]*/, htmlVideoKeyMatch = [
/player=new/,
/<div id="video"/,
/<div id="[^"]*?player"/,
/\/\/视频链接/,
/HlsJsPlayer\(/,
/<iframe[\s\S]*?src="[^"]+?"/,
/<video[\s\S]*?src="[^"]+?"/
], parseUrlMap = new Map();
async function init(_0x251cc1) {
const _0x3f2b5f = _0x24a000, _0x45ef76 = { 'wRtKU': _0x3f2b5f(0x337) };
siteKey = _0x251cc1[_0x3f2b5f(0x1f6)], siteType = _0x251cc1[_0x3f2b5f(0x351)], host = _0x251cc1[_0x3f2b5f(0x338)], _0x251cc1[_0x3f2b5f(0x338)][_0x3f2b5f(0x3b3) + _0x3f2b5f(0x2f2)](_0x45ef76[_0x3f2b5f(0x204)]) && (host = _0x251cc1[_0x3f2b5f(0x338)][_0x3f2b5f(0x337)], siteJx = _0x251cc1[_0x3f2b5f(0x338)]);
}
;
async function request(_0x1922aa, _0x22bcdb, _0x3dfda0 = 0x1f39 * -0x1 + 0xb81e + 0x1b29 * 0x3) {
const _0x341df3 = _0x24a000, _0x56e6da = {
'ePAKK': function (_0x5d5218, _0x1a8370, _0x9b9062) {
return _0x5d5218(_0x1a8370, _0x9b9062);
},
'BIDOf': _0x341df3(0x24f),
'qhbab': _0x341df3(0x3b0) + _0x341df3(0x221) + _0x341df3(0x244) + _0x341df3(0x2d8) + _0x341df3(0x3af) + _0x341df3(0x203) + _0x341df3(0x31a) + _0x341df3(0x37b) + _0x341df3(0x1f9) + _0x341df3(0x264) + _0x341df3(0x2fa) + _0x341df3(0x2d5) + '6'
};
let _0x3869e9 = await _0x56e6da[_0x341df3(0x395)](req, _0x1922aa, {
'method': _0x56e6da[_0x341df3(0x1ec)],
'headers': _0x22bcdb ? _0x22bcdb : { 'User-Agent': _0x56e6da[_0x341df3(0x271)] },
'timeout': _0x3dfda0
});
return _0x3869e9[_0x341df3(0x217)];
}
async function home(_0xa33cbc) {
const _0x2ff6d6 = _0x24a000, _0x2fec26 = {
'IKCWR': _0x2ff6d6(0x288),
'VYHXK': _0x2ff6d6(0x2cf) + 'od',
'mSlqf': function (_0x4c5b77, _0x3a09ed, _0x3fbbd2) {
return _0x4c5b77(_0x3a09ed, _0x3fbbd2);
},
'KRVeJ': function (_0x190297, _0x45264b) {
return _0x190297(_0x45264b);
},
'eRIpS': function (_0xca9da7, _0x4f9386) {
return _0xca9da7(_0x4f9386);
},
'KitoD': function (_0x48bb51, _0x3240c8, _0x3ad21f) {
return _0x48bb51(_0x3240c8, _0x3ad21f);
},
'Udbgi': function (_0x3cd1ee, _0x3ef8c5) {
return _0x3cd1ee(_0x3ef8c5);
},
'fcPwA': _0x2ff6d6(0x2f9),
'XhjKd': _0x2ff6d6(0x394),
'MAPTF': _0x2ff6d6(0x339),
'HHuLq': function (_0x1ed1aa, _0x3ca419, _0x512ce1) {
return _0x1ed1aa(_0x3ca419, _0x512ce1);
},
'jBTDy': function (_0x56e141, _0x4ee936) {
return _0x56e141 < _0x4ee936;
},
'bgAzg': function (_0x5a1b87, _0x5b81d3) {
return _0x5a1b87 != _0x5b81d3;
},
'YfnZq': function (_0x316826, _0x80e0c3) {
return _0x316826 < _0x80e0c3;
},
'MWcjN': function (_0x3f7e11, _0x521db4) {
return _0x3f7e11(_0x521db4);
},
'ofHAn': function (_0x9b4e48, _0x5c839e) {
return _0x9b4e48 === _0x5c839e;
},
'vuXnk': _0x2ff6d6(0x256),
'yKQXX': function (_0x73142b, _0xdf899b) {
return _0x73142b === _0xdf899b;
},
'iZers': _0x2ff6d6(0x27b),
'IpeiC': _0x2ff6d6(0x355),
'nvSRb': function (_0x338866, _0x10950f) {
return _0x338866 < _0x10950f;
},
'zMZmQ': function (_0x5c8e41, _0x3705da) {
return _0x5c8e41(_0x3705da);
},
'IWfGL': function (_0x2e630a, _0x68fcc3) {
return _0x2e630a + _0x68fcc3;
},
'pksWn': _0x2ff6d6(0x202),
'QZvys': _0x2ff6d6(0x22d)
};
try {
if (host[_0x2ff6d6(0x39f)](_0x2fec26[_0x2ff6d6(0x2ef)]) || host[_0x2ff6d6(0x39f)](_0x2fec26[_0x2ff6d6(0x3cc)])) {
const _0x5dddec = host, _0xac6d0f = await _0x2fec26[_0x2ff6d6(0x36a)](request, _0x5dddec, _0x2fec26[_0x2ff6d6(0x319)](getHeaders, _0x5dddec)), _0x3885b5 = JSON[_0x2ff6d6(0x213)](_0xac6d0f), _0x5c6b02 = { 'class': [] };
if (_0x3885b5[_0x2ff6d6(0x2f9)] && Array[_0x2ff6d6(0x315)](_0x3885b5[_0x2ff6d6(0x2f9)]))
for (const _0x31e7ca of _0x3885b5[_0x2ff6d6(0x2f9)]) {
const _0x2d6dd5 = _0x31e7ca[_0x2ff6d6(0x37d)];
if (_0x2fec26[_0x2ff6d6(0x319)](isBan, _0x2d6dd5))
continue;
_0x5c6b02[_0x2ff6d6(0x2f9)][_0x2ff6d6(0x332)]({
'type_id': _0x31e7ca[_0x2ff6d6(0x3c5)],
'type_name': _0x2d6dd5
});
}
return JSON[_0x2ff6d6(0x3a2)](_0x5c6b02);
} else {
let _0x532bb3 = _0x2fec26[_0x2ff6d6(0x368)](getCateUrl, host), _0xf10025 = null;
if (_0x532bb3) {
const _0x4a9315 = await _0x2fec26[_0x2ff6d6(0x201)](request, _0x532bb3, _0x2fec26[_0x2ff6d6(0x223)](getHeaders, _0x532bb3)), _0x4c79fb = JSON[_0x2ff6d6(0x213)](_0x4a9315);
if (_0x4c79fb[_0x2ff6d6(0x3b3) + _0x2ff6d6(0x2f2)](_0x2fec26[_0x2ff6d6(0x28b)]) && Array[_0x2ff6d6(0x315)](_0x4c79fb[_0x2ff6d6(0x2f9)]))
_0xf10025 = _0x4c79fb[_0x2ff6d6(0x2f9)];
else {
if (_0x4c79fb[_0x2ff6d6(0x3b3) + _0x2ff6d6(0x2f2)](_0x2fec26[_0x2ff6d6(0x23e)]) && Array[_0x2ff6d6(0x315)](_0x4c79fb[_0x2ff6d6(0x394)]))
_0xf10025 = _0x4c79fb[_0x2ff6d6(0x394)];
else {
if (_0x4c79fb[_0x2ff6d6(0x3b3) + _0x2ff6d6(0x2f2)](_0x2fec26[_0x2ff6d6(0x33b)]) && _0x4c79fb[_0x2ff6d6(0x339)][_0x2ff6d6(0x3b3) + _0x2ff6d6(0x2f2)](_0x2fec26[_0x2ff6d6(0x23e)]) && Array[_0x2ff6d6(0x315)](_0x4c79fb[_0x2ff6d6(0x339)][_0x2ff6d6(0x394)]))
_0xf10025 = _0x4c79fb[_0x2ff6d6(0x339)][_0x2ff6d6(0x394)];
else
_0x4c79fb[_0x2ff6d6(0x3b3) + _0x2ff6d6(0x2f2)](_0x2fec26[_0x2ff6d6(0x33b)]) && Array[_0x2ff6d6(0x315)](_0x4c79fb[_0x2ff6d6(0x339)]) && (_0xf10025 = _0x4c79fb[_0x2ff6d6(0x339)]);
}
}
} else {
const _0x592327 = _0x2fec26[_0x2ff6d6(0x2a9)](getFilterTypes, _0x532bb3, null), _0x1fc904 = _0x592327[_0x2ff6d6(0x265)]('\x0a')[-0x1e38 + -0x4ac + 0x22e4][_0x2ff6d6(0x265)]('+');
_0xf10025 = [];
for (let _0x2a35a4 = -0x23f3 + -0x1b84 + 0x3f78; _0x2fec26[_0x2ff6d6(0x1e4)](_0x2a35a4, _0x1fc904[_0x2ff6d6(0x2d3)]); _0x2a35a4++) {
const _0x3f713c = _0x1fc904[_0x2a35a4][_0x2ff6d6(0x314)]()[_0x2ff6d6(0x265)]('=');
if (_0x2fec26[_0x2ff6d6(0x1e4)](_0x3f713c[_0x2ff6d6(0x2d3)], -0x3d1 + 0x18cc + -0x5b * 0x3b))
continue;
const _0x101b02 = {
'type_name': _0x3f713c[-0xa12 + 0x5d * -0x5b + 0x2b21][_0x2ff6d6(0x314)](),
'type_id': _0x3f713c[-0x1140 * 0x2 + 0x1 * 0x20fd + 0x2 * 0xc2][_0x2ff6d6(0x314)]()
};
_0xf10025[_0x2ff6d6(0x332)](_0x101b02);
}
}
const _0x4d7ad6 = { 'class': [] };
if (_0x2fec26[_0x2ff6d6(0x1f1)](_0xf10025, null))
for (let _0x29d748 = -0x1d * 0xd3 + -0x2e7 * -0xb + -0x806; _0x2fec26[_0x2ff6d6(0x20c)](_0x29d748, _0xf10025[_0x2ff6d6(0x2d3)]); _0x29d748++) {
const _0xe71e4e = _0xf10025[_0x29d748], _0x14164f = _0xe71e4e[_0x2ff6d6(0x37d)];
if (_0x2fec26[_0x2ff6d6(0x347)](isBan, _0x14164f))
continue;
const _0x52590c = _0xe71e4e[_0x2ff6d6(0x3c5)], _0x8127ab = {
'type_id': _0x52590c,
'type_name': _0x14164f
}, _0x5a5e97 = _0xe71e4e[_0x2ff6d6(0x2e9) + 'd'];
if (_0xa33cbc) {
const _0x2dd17b = _0x2fec26[_0x2ff6d6(0x201)](getFilterTypes, _0x532bb3, _0x5a5e97), _0x25dbda = _0x2dd17b[_0x2ff6d6(0x265)]('\x0a'), _0x409116 = [];
for (let _0x219e87 = _0x532bb3 ? -0x55b + -0x137f + 0x9 * 0x2c3 : 0x9f4 + -0x1 * 0xea2 + -0x257 * -0x2; _0x2fec26[_0x2ff6d6(0x20c)](_0x219e87, _0x25dbda[_0x2ff6d6(0x2d3)]); _0x219e87++) {
const _0x146f59 = _0x25dbda[_0x219e87][_0x2ff6d6(0x314)]();
if (!_0x146f59)
continue;
const _0x3bb665 = _0x146f59[_0x2ff6d6(0x265)]('+');
let _0x128e29 = _0x3bb665[0x204 * 0x10 + 0x19b2 + -0x39f2][_0x2ff6d6(0x314)](), _0x50cbc4 = _0x128e29;
if (_0x128e29[_0x2ff6d6(0x39f)]('筛选')) {
_0x128e29 = _0x128e29[_0x2ff6d6(0x2e5)](/筛选/g, '');
if (_0x2fec26[_0x2ff6d6(0x307)](_0x128e29, _0x2fec26[_0x2ff6d6(0x28b)]))
_0x50cbc4 = '类型';
else {
if (_0x2fec26[_0x2ff6d6(0x307)](_0x128e29, _0x2fec26[_0x2ff6d6(0x3bb)]))
_0x50cbc4 = '地区';
else {
if (_0x2fec26[_0x2ff6d6(0x38f)](_0x128e29, _0x2fec26[_0x2ff6d6(0x3ae)]))
_0x50cbc4 = '语言';
else {
if (_0x2fec26[_0x2ff6d6(0x38f)](_0x128e29, _0x2fec26[_0x2ff6d6(0x31c)]))
_0x50cbc4 = '年份';
}
}
}
}
const _0xb82e8e = {
'key': _0x128e29,
'name': _0x50cbc4,
'value': []
};
for (let _0x5edb78 = -0xfc6 + -0x264c + 0x3613; _0x2fec26[_0x2ff6d6(0x2ba)](_0x5edb78, _0x3bb665[_0x2ff6d6(0x2d3)]); _0x5edb78++) {
const _0x4996ce = _0x3bb665[_0x5edb78][_0x2ff6d6(0x314)](), _0xea216e = _0x4996ce[_0x2ff6d6(0x259)]('=');
if (_0x2fec26[_0x2ff6d6(0x38f)](_0xea216e, -(0x5 * 0x2c1 + -0x817 + -0x5ad * 0x1))) {
if (_0x2fec26[_0x2ff6d6(0x2f8)](isBan, _0x4996ce))
continue;
_0xb82e8e[_0x2ff6d6(0x215)][_0x2ff6d6(0x332)]({
'n': _0x4996ce,
'v': _0x4996ce
});
} else {
const _0x53eb94 = _0x4996ce[_0x2ff6d6(0x353)](0x5a * 0x40 + 0xcf4 + -0x2374, _0xea216e);
if (_0x2fec26[_0x2ff6d6(0x319)](isBan, _0x53eb94))
continue;
_0xb82e8e[_0x2ff6d6(0x215)][_0x2ff6d6(0x332)]({
'n': _0x53eb94[_0x2ff6d6(0x314)](),
'v': _0x4996ce[_0x2ff6d6(0x353)](_0x2fec26[_0x2ff6d6(0x2b3)](_0xea216e, 0xb75 + -0xb * 0x209 + -0x3 * -0x3a5))[_0x2ff6d6(0x314)]()
});
}
}
_0x409116[_0x2ff6d6(0x332)](_0xb82e8e);
}
!_0x4d7ad6[_0x2ff6d6(0x3b3) + _0x2ff6d6(0x2f2)](_0x2fec26[_0x2ff6d6(0x1f7)]) && (_0x4d7ad6[_0x2ff6d6(0x202)] = {}), _0x4d7ad6[_0x2ff6d6(0x202)][_0x52590c] = _0x409116;
}
_0x4d7ad6[_0x2ff6d6(0x2f9)][_0x2ff6d6(0x332)](_0x8127ab);
}
return JSON[_0x2ff6d6(0x3a2)](_0x4d7ad6);
}
} catch (_0x4342ba) {
SpiderDebug[_0x2ff6d6(0x24a)](_0x2fec26[_0x2ff6d6(0x2b3)](_0x2fec26[_0x2ff6d6(0x2f1)], _0x4342ba));
}
return JSON[_0x2ff6d6(0x3a2)]({ 'class': [] });
}
async function homeVod() {
const _0x4ef343 = _0x24a000, _0x3a4f7 = {
'nFrDW': _0x4ef343(0x288),
'umjti': _0x4ef343(0x2cf) + 'od',
'WpxrU': function (_0x4b2ec1, _0xc144ce, _0x5dd372) {
return _0x4b2ec1(_0xc144ce, _0x5dd372);
},
'OIKvw': function (_0xf764d5, _0x2b3261) {
return _0xf764d5(_0x2b3261);
},
'Zelfl': function (_0x24e988, _0x4995a4) {
return _0x24e988(_0x4995a4);
},
'EeHWO': function (_0x26a41a, _0x366d23) {
return _0x26a41a + _0x366d23;
},
'SKgeb': function (_0x5d0c6e, _0x19c7d9) {
return _0x5d0c6e(_0x19c7d9);
},
'FEuLQ': _0x4ef343(0x382) + _0x4ef343(0x2af) + _0x4ef343(0x361) + '=',
'Uqurg': function (_0x408853, _0x35aef7, _0x3b369b) {
return _0x408853(_0x35aef7, _0x3b369b);
},
'mWrNJ': function (_0x1f7197, _0x9a8c24) {
return _0x1f7197(_0x9a8c24);
},
'nQbvl': function (_0x1084e1, _0x1ca4f6) {
return _0x1084e1 < _0x1ca4f6;
},
'uUBbz': function (_0x323e4d, _0x5c53cc, _0x416c5e, _0x1f06cd) {
return _0x323e4d(_0x5c53cc, _0x416c5e, _0x1f06cd);
},
'znjdK': _0x4ef343(0x2d4),
'TmtUN': function (_0x41b69c, _0x2368eb) {
return _0x41b69c === _0x2368eb;
},
'hPgPi': _0x4ef343(0x2ac)
};
try {
if (host[_0x4ef343(0x39f)](_0x3a4f7[_0x4ef343(0x254)]) || host[_0x4ef343(0x39f)](_0x3a4f7[_0x4ef343(0x2b6)])) {
const _0x5bce52 = host + (_0x4ef343(0x324) + _0x4ef343(0x3c8) + '=1'), _0x514244 = await _0x3a4f7[_0x4ef343(0x37f)](request, _0x5bce52, _0x3a4f7[_0x4ef343(0x2d2)](getHeaders, _0x5bce52)), _0x24a0af = JSON[_0x4ef343(0x213)](_0x514244), _0x56d03d = [];
if (_0x24a0af[_0x4ef343(0x394)] && Array[_0x4ef343(0x315)](_0x24a0af[_0x4ef343(0x394)]))
for (const _0x13ff34 of _0x24a0af[_0x4ef343(0x394)]) {
_0x56d03d[_0x4ef343(0x332)]({
'vod_id': _0x13ff34[_0x4ef343(0x3c3)],
'vod_name': _0x13ff34[_0x4ef343(0x2b8)],
'vod_pic': _0x13ff34[_0x4ef343(0x290)] || '',
'vod_remarks': _0x13ff34[_0x4ef343(0x346) + 's'] || ''
});
}
return JSON[_0x4ef343(0x3a2)]({ 'list': _0x56d03d });
} else {
const _0x5ae89d = host;
let _0x298455 = _0x3a4f7[_0x4ef343(0x239)](getRecommendUrl, _0x5ae89d), _0xa3fd7c = ![];
!_0x298455 && (_0x298455 = _0x3a4f7[_0x4ef343(0x359)](_0x3a4f7[_0x4ef343(0x277)](getCateFilterUrlPrefix, _0x5ae89d), _0x3a4f7[_0x4ef343(0x279)]), _0xa3fd7c = !![]);
const _0x431560 = await _0x3a4f7[_0x4ef343(0x233)](request, _0x298455, _0x3a4f7[_0x4ef343(0x25e)](getHeaders, _0x298455)), _0x56c7e8 = JSON[_0x4ef343(0x213)](_0x431560), _0x5853d3 = [];
if (_0xa3fd7c) {
const _0x3997ca = _0x56c7e8[_0x4ef343(0x339)];
for (let _0x29f049 = -0x3a1 * -0x7 + -0x2e2 + -0x1685; _0x3a4f7[_0x4ef343(0x3b2)](_0x29f049, _0x3997ca[_0x4ef343(0x2d3)]); _0x29f049++) {
const _0x260601 = _0x3997ca[_0x29f049], _0x24c0c0 = {
'vod_id': _0x260601[_0x4ef343(0x3b6)],
'vod_name': _0x260601[_0x4ef343(0x1e9)],
'vod_pic': _0x260601[_0x4ef343(0x3ba)],
'vod_remarks': _0x260601[_0x4ef343(0x258)]
};
_0x5853d3[_0x4ef343(0x332)](_0x24c0c0);
}
} else {
const _0x2ab595 = [];
_0x3a4f7[_0x4ef343(0x276)](findJsonArray, _0x56c7e8, _0x3a4f7[_0x4ef343(0x2ed)], _0x2ab595);
_0x3a4f7[_0x4ef343(0x317)](_0x2ab595[_0x4ef343(0x2d3)], 0x176e * -0x1 + -0x6 * 0x20 + -0x182e * -0x1) && _0x3a4f7[_0x4ef343(0x276)](findJsonArray, _0x56c7e8, _0x3a4f7[_0x4ef343(0x344)], _0x2ab595);
const _0x4b7c8b = [];
for (const _0x442e26 of _0x2ab595) {
for (let _0x2b0473 = -0x33b * 0x6 + 0x1 * -0x1f7 + 0x1559; _0x3a4f7[_0x4ef343(0x3b2)](_0x2b0473, _0x442e26[_0x4ef343(0x2d3)]); _0x2b0473++) {
const _0x3dbd8d = _0x442e26[_0x2b0473], _0x5c8547 = _0x3dbd8d[_0x4ef343(0x3c3)];
if (_0x4b7c8b[_0x4ef343(0x39f)](_0x5c8547))
continue;
_0x4b7c8b[_0x4ef343(0x332)](_0x5c8547);
const _0x3523d6 = {
'vod_id': _0x5c8547,
'vod_name': _0x3dbd8d[_0x4ef343(0x2b8)],
'vod_pic': _0x3dbd8d[_0x4ef343(0x290)],
'vod_remarks': _0x3dbd8d[_0x4ef343(0x346) + 's']
};
_0x5853d3[_0x4ef343(0x332)](_0x3523d6);
}
}
}
const _0x21c5c9 = { 'list': _0x5853d3 };
return JSON[_0x4ef343(0x3a2)](_0x21c5c9);
}
} catch (_0x2c9625) {
SpiderDebug[_0x4ef343(0x24a)](_0x2c9625);
}
return '';
}
async function category(_0x17bc49, _0x327387, _0x2f500e, _0x490196) {
const _0x2dea72 = _0x24a000, _0x1eac02 = {
'ghVBe': _0x2dea72(0x288),
'dftSy': _0x2dea72(0x2cf) + 'od',
'NthFz': function (_0x36a38a, _0x2942af, _0xdb7a9c) {
return _0x36a38a(_0x2942af, _0xdb7a9c);
},
'fUjyK': function (_0xa434ff, _0x705e82) {
return _0xa434ff(_0x705e82);
},
'xIbro': function (_0x188c3b, _0x5cc548) {
return _0x188c3b + _0x5cc548;
},
'YmXhB': function (_0x9cc843, _0x4ef04e) {
return _0x9cc843(_0x4ef04e);
},
'xAftd': function (_0x243acc, _0x54bfd9) {
return _0x243acc(_0x54bfd9);
},
'mEBLG': function (_0x276e23, _0x50f675) {
return _0x276e23 !== _0x50f675;
},
'eCaVc': function (_0x42bb55, _0x104923) {
return _0x42bb55 === _0x104923;
},
'IkIJp': _0x2dea72(0x36f),
'xUxPS': function (_0x273158, _0xd54879) {
return _0x273158 !== _0xd54879;
},
'ZuLFK': function (_0x36cbb1, _0x2946b1) {
return _0x36cbb1 === _0x2946b1;
},
'LtQsE': _0x2dea72(0x345),
'bkKAx': function (_0x40b381, _0x4ac366) {
return _0x40b381 !== _0x4ac366;
},
'vgGfV': function (_0x2a64e1, _0x116f66) {
return _0x2a64e1 !== _0x116f66;
},
'qrmQn': function (_0x2a2af5, _0x95b9cb) {
return _0x2a2af5 === _0x95b9cb;
},
'AsjQf': function (_0x7b8eef, _0x33e37f) {
return _0x7b8eef % _0x33e37f;
},
'QDURc': function (_0x39edd0, _0x2b3f5f) {
return _0x39edd0 / _0x2b3f5f;
},
'fmHZd': function (_0x48b5be, _0x57063b) {
return _0x48b5be / _0x57063b;
},
'YTcha': function (_0x39dd2a, _0x3e0046) {
return _0x39dd2a !== _0x3e0046;
},
'bkfnv': function (_0x387233, _0x40a0b1) {
return _0x387233 !== _0x40a0b1;
},
'fBrnR': function (_0x11978c, _0x4dbbc2) {
return _0x11978c !== _0x4dbbc2;
},
'HUsMa': function (_0x3993cf, _0x232042) {
return _0x3993cf !== _0x232042;
},
'xaxYD': function (_0x429fdd, _0xe751e7) {
return _0x429fdd < _0xe751e7;
}
};
try {
if (host[_0x2dea72(0x39f)](_0x1eac02[_0x2dea72(0x32a)]) || host[_0x2dea72(0x39f)](_0x1eac02[_0x2dea72(0x35e)])) {
const _0x5db283 = host + (_0x2dea72(0x324) + _0x2dea72(0x23f)) + _0x17bc49 + _0x2dea72(0x2bd) + _0x327387, _0x50a032 = await _0x1eac02[_0x2dea72(0x20b)](request, _0x5db283, _0x1eac02[_0x2dea72(0x328)](getHeaders, _0x5db283)), _0x1ea1bd = JSON[_0x2dea72(0x213)](_0x50a032), _0x2740e5 = [];
if (_0x1ea1bd[_0x2dea72(0x394)] && Array[_0x2dea72(0x315)](_0x1ea1bd[_0x2dea72(0x394)]))
for (const _0x31d55a of _0x1ea1bd[_0x2dea72(0x394)]) {
_0x2740e5[_0x2dea72(0x332)]({
'vod_id': _0x31d55a[_0x2dea72(0x3c3)],
'vod_name': _0x31d55a[_0x2dea72(0x2b8)],
'vod_pic': _0x31d55a[_0x2dea72(0x290)] || '',
'vod_remarks': _0x31d55a[_0x2dea72(0x346) + 's'] || ''
});
}
return JSON[_0x2dea72(0x3a2)]({
'page': _0x327387,
'pagecount': _0x1ea1bd[_0x2dea72(0x2ce)] || -0x103a + 0x226f + 0x1 * -0x1234,
'limit': _0x1ea1bd[_0x2dea72(0x23c)] || 0x249e + -0xcb * -0x8 + -0x2ae2,
'total': _0x1ea1bd[_0x2dea72(0x399)] || -0xbd2 + 0x7b8 * 0x5 + -0x2 * 0xd63,
'list': _0x2740e5
});
} else {
const _0x125b73 = host;
let _0x24aebb = _0x1eac02[_0x2dea72(0x371)](_0x1eac02[_0x2dea72(0x371)](_0x1eac02[_0x2dea72(0x397)](getCateFilterUrlPrefix, _0x125b73), _0x17bc49), _0x1eac02[_0x2dea72(0x20a)](getCateFilterUrlSuffix, _0x125b73));
_0x24aebb = _0x24aebb[_0x2dea72(0x2e5)](/#PN#/g, _0x327387), _0x24aebb = _0x24aebb[_0x2dea72(0x2e5)](/筛选class/g, _0x490196?.[_0x2dea72(0x2f9)] ?? ''), _0x24aebb = _0x24aebb[_0x2dea72(0x2e5)](/筛选area/g, _0x490196?.[_0x2dea72(0x256)] ?? ''), _0x24aebb = _0x24aebb[_0x2dea72(0x2e5)](/筛选lang/g, _0x490196?.[_0x2dea72(0x27b)] ?? ''), _0x24aebb = _0x24aebb[_0x2dea72(0x2e5)](/筛选year/g, _0x490196?.[_0x2dea72(0x355)] ?? ''), _0x24aebb = _0x24aebb[_0x2dea72(0x2e5)](/排序/g, _0x490196?.['排序'] ?? '');
const _0x30d3a8 = await _0x1eac02[_0x2dea72(0x20b)](request, _0x24aebb, _0x1eac02[_0x2dea72(0x397)](getHeaders, _0x24aebb)), _0x58b8b5 = JSON[_0x2dea72(0x213)](_0x30d3a8);
let _0x41f388 = Infinity;
try {
if (_0x1eac02[_0x2dea72(0x32b)](_0x58b8b5[_0x2dea72(0x388)], undefined) && _0x1eac02[_0x2dea72(0x2b9)](typeof _0x58b8b5[_0x2dea72(0x388)], _0x1eac02[_0x2dea72(0x3c0)]))
_0x41f388 = _0x58b8b5[_0x2dea72(0x388)];
else {
if (_0x1eac02[_0x2dea72(0x39d)](_0x58b8b5[_0x2dea72(0x2ce)], undefined) && _0x1eac02[_0x2dea72(0x2b9)](typeof _0x58b8b5[_0x2dea72(0x2ce)], _0x1eac02[_0x2dea72(0x3c0)]))
_0x41f388 = _0x58b8b5[_0x2dea72(0x2ce)];
else {
if (_0x1eac02[_0x2dea72(0x32b)](_0x58b8b5[_0x2dea72(0x339)], undefined) && _0x1eac02[_0x2dea72(0x35f)](typeof _0x58b8b5[_0x2dea72(0x339)], _0x1eac02[_0x2dea72(0x393)]) && _0x1eac02[_0x2dea72(0x229)](_0x58b8b5[_0x2dea72(0x339)][_0x2dea72(0x399)], undefined) && _0x1eac02[_0x2dea72(0x35f)](typeof _0x58b8b5[_0x2dea72(0x339)][_0x2dea72(0x399)], _0x1eac02[_0x2dea72(0x3c0)]) && _0x1eac02[_0x2dea72(0x392)](_0x58b8b5[_0x2dea72(0x339)][_0x2dea72(0x23c)], undefined) && _0x1eac02[_0x2dea72(0x2b9)](typeof _0x58b8b5[_0x2dea72(0x339)][_0x2dea72(0x23c)], _0x1eac02[_0x2dea72(0x3c0)])) {
const _0x2ef68b = _0x58b8b5[_0x2dea72(0x339)][_0x2dea72(0x23c)], _0x1bec69 = _0x58b8b5[_0x2dea72(0x339)][_0x2dea72(0x399)];
_0x41f388 = _0x1eac02[_0x2dea72(0x2a0)](_0x1eac02[_0x2dea72(0x302)](_0x1bec69, _0x2ef68b), -0x35f + -0xf9 * -0x19 + -0x14f2) ? _0x1eac02[_0x2dea72(0x2d9)](_0x1bec69, _0x2ef68b) : _0x1eac02[_0x2dea72(0x371)](Math[_0x2dea72(0x33d)](_0x1eac02[_0x2dea72(0x33f)](_0x1bec69, _0x2ef68b)), -0x834 + -0x1 * -0x24bc + 0x1c87 * -0x1);
}
}
}
} catch (_0x5c73e6) {
SpiderDebug[_0x2dea72(0x24a)](_0x5c73e6);
}
const _0x42d73c = _0x1eac02[_0x2dea72(0x2e8)](_0x58b8b5[_0x2dea72(0x394)], undefined) ? _0x58b8b5[_0x2dea72(0x394)] : _0x1eac02[_0x2dea72(0x280)](_0x58b8b5[_0x2dea72(0x339)], undefined) && _0x1eac02[_0x2dea72(0x273)](_0x58b8b5[_0x2dea72(0x339)][_0x2dea72(0x394)], undefined) ? _0x58b8b5[_0x2dea72(0x339)][_0x2dea72(0x394)] : _0x58b8b5[_0x2dea72(0x339)], _0x35c38d = [];
if (_0x1eac02[_0x2dea72(0x30a)](_0x42d73c, undefined))
for (let _0x124862 = 0xc3d + 0x1ee1 * 0x1 + -0x2b1e; _0x1eac02[_0x2dea72(0x2bf)](_0x124862, _0x42d73c[_0x2dea72(0x2d3)]); _0x124862++) {
const _0xa38597 = _0x42d73c[_0x124862], _0xf5aa7f = {
'vod_id': _0x1eac02[_0x2dea72(0x280)](_0xa38597[_0x2dea72(0x3c3)], undefined) ? _0xa38597[_0x2dea72(0x3c3)] : _0xa38597[_0x2dea72(0x3b6)],
'vod_name': _0x1eac02[_0x2dea72(0x39d)](_0xa38597[_0x2dea72(0x2b8)], undefined) ? _0xa38597[_0x2dea72(0x2b8)] : _0xa38597[_0x2dea72(0x1e9)],
'vod_pic': _0x1eac02[_0x2dea72(0x32b)](_0xa38597[_0x2dea72(0x290)], undefined) ? _0xa38597[_0x2dea72(0x290)] : _0xa38597[_0x2dea72(0x3ba)],
'vod_remarks': _0x1eac02[_0x2dea72(0x273)](_0xa38597[_0x2dea72(0x346) + 's'], undefined) ? _0xa38597[_0x2dea72(0x346) + 's'] : _0xa38597[_0x2dea72(0x258)]
};
_0x35c38d[_0x2dea72(0x332)](_0xf5aa7f);
}
const _0x307572 = {
'page': _0x327387,
'pagecount': _0x41f388,
'limit': 0x5a,
'total': Infinity,
'list': _0x35c38d
};
return JSON[_0x2dea72(0x3a2)](_0x307572);
}
} catch (_0x2a89be) {
SpiderDebug[_0x2dea72(0x24a)](_0x2a89be);
}
return '';
}
async function detail(_0x26f995) {
const _0x8ea006 = _0x24a000, _0x52e3d6 = {
'fIzpG': _0x8ea006(0x288),
'gINFD': _0x8ea006(0x2cf) + 'od',
'MJeua': function (_0x44bc08, _0x173641, _0x19a96a) {
return _0x44bc08(_0x173641, _0x19a96a);
},
'WodPN': function (_0x311305, _0xcfa1c8) {
return _0x311305(_0xcfa1c8);
},
'wpdZs': function (_0x52de8f, _0x5bbd8c) {
return _0x52de8f + _0x5bbd8c;
},
'zFyTh': function (_0x4317fb, _0x28ea86, _0x2e16e5, _0x35fbcc, _0x136e93, _0x19c8f1) {
return _0x4317fb(_0x28ea86, _0x2e16e5, _0x35fbcc, _0x136e93, _0x19c8f1);
}
};
try {
if (host[_0x8ea006(0x39f)](_0x52e3d6[_0x8ea006(0x2f3)]) || host[_0x8ea006(0x39f)](_0x52e3d6[_0x8ea006(0x240)])) {
const _0x31ce10 = host + (_0x8ea006(0x230) + _0x8ea006(0x374)) + _0x26f995, _0x5893d7 = await _0x52e3d6[_0x8ea006(0x253)](request, _0x31ce10, _0x52e3d6[_0x8ea006(0x29a)](getHeaders, _0x31ce10)), _0x1957f1 = JSON[_0x8ea006(0x213)](_0x5893d7), _0x3e04fe = { 'list': [] }, _0x3c884c = {}, _0x391656 = _0x1957f1[_0x8ea006(0x394)] && _0x1957f1[_0x8ea006(0x394)][-0xd79 + 0xea0 + -0x127] ? _0x1957f1[_0x8ea006(0x394)][0x20e * -0x1 + -0x44 * 0x4c + 0x163e * 0x1] : {};
return _0x3c884c[_0x8ea006(0x3c3)] = _0x391656[_0x8ea006(0x3c3)] || _0x26f995, _0x3c884c[_0x8ea006(0x2b8)] = _0x391656[_0x8ea006(0x2b8)] || '', _0x3c884c[_0x8ea006(0x290)] = _0x391656[_0x8ea006(0x290)] || '', _0x3c884c[_0x8ea006(0x37d)] = _0x391656[_0x8ea006(0x37d)] || '', _0x3c884c[_0x8ea006(0x32c)] = _0x391656[_0x8ea006(0x32c)] || '', _0x3c884c[_0x8ea006(0x228)] = _0x391656[_0x8ea006(0x228)] || '', _0x3c884c[_0x8ea006(0x346) + 's'] = _0x391656[_0x8ea006(0x346) + 's'] || '', _0x3c884c[_0x8ea006(0x23d)] = _0x391656[_0x8ea006(0x23d)] || '', _0x3c884c[_0x8ea006(0x2cd) + 'or'] = _0x391656[_0x8ea006(0x2cd) + 'or'] || '', _0x3c884c[_0x8ea006(0x227) + 't'] = _0x391656[_0x8ea006(0x227) + 't'] || '', _0x3c884c[_0x8ea006(0x34d) + _0x8ea006(0x3bf)] = _0x391656[_0x8ea006(0x34d) + _0x8ea006(0x3bf)] || '', _0x3c884c[_0x8ea006(0x3a0) + 'rl'] = _0x391656[_0x8ea006(0x3a0) + 'rl'] || '', _0x3e04fe[_0x8ea006(0x394)][_0x8ea006(0x332)](_0x3c884c), JSON[_0x8ea006(0x3a2)](_0x3e04fe);
} else {
const _0x1352d2 = host, _0x5127a9 = _0x52e3d6[_0x8ea006(0x31e)](_0x52e3d6[_0x8ea006(0x29a)](getPlayUrlPrefix, _0x1352d2), _0x26f995), _0x5f713e = await _0x52e3d6[_0x8ea006(0x253)](request, _0x5127a9, _0x52e3d6[_0x8ea006(0x29a)](getHeaders, _0x5127a9)), _0x3e8d52 = JSON[_0x8ea006(0x213)](_0x5f713e), _0x3536cc = { 'list': [] }, _0x1c7671 = {};
return _0x52e3d6[_0x8ea006(0x30e)](genPlayList, _0x1352d2, _0x3e8d52, _0x5f713e, _0x1c7671, _0x26f995), _0x3536cc[_0x8ea006(0x394)][_0x8ea006(0x332)](_0x1c7671), JSON[_0x8ea006(0x3a2)](_0x3536cc);
}
} catch (_0x40e06f) {
SpiderDebug[_0x8ea006(0x24a)](_0x40e06f);
}
return '';
}
async function play(_0x314f8e, _0x533915, _0x14a1d6) {
const _0x5ed43f = _0x24a000, _0x46895d = {
'rfYvZ': function (_0x146ae4, _0x119a4f) {
return _0x146ae4 === _0x119a4f;
},
'rQSdz': _0x5ed43f(0x2d1) + _0x5ed43f(0x341) + _0x5ed43f(0x349) + _0x5ed43f(0x2db) + _0x5ed43f(0x2ec) + _0x5ed43f(0x218) + _0x5ed43f(0x304),
'zlCKO': function (_0x79100f, _0x50fda5) {
return _0x79100f > _0x50fda5;
},
'AEWJN': function (_0x34e794, _0x24610e, _0x529315, _0x31bacd) {
return _0x34e794(_0x24610e, _0x529315, _0x31bacd);
},
'Knznh': function (_0x4f4e7d, _0x5a0aac) {
return _0x4f4e7d !== _0x5a0aac;
},
'ViinS': function (_0x595f7e, _0x159136) {
return _0x595f7e(_0x159136);
}
};
try {
let _0xabb5ea = siteJx[_0x314f8e];
!_0xabb5ea && (siteJx[_0x5ed43f(0x3b3) + _0x5ed43f(0x2f2)]('*') ? _0xabb5ea = siteJx['*'] : _0xabb5ea = []);
_0x46895d[_0x5ed43f(0x28d)](_0xabb5ea[_0x5ed43f(0x2d3)], 0x6 * -0x2c7 + 0xf * -0x1a5 + 0xdc7 * 0x3) && (_0xabb5ea = [_0x46895d[_0x5ed43f(0x27e)]]);
if (_0x46895d[_0x5ed43f(0x24b)](_0xabb5ea[_0x5ed43f(0x2d3)], -0xf * 0x73 + 0x13df + -0xd22 * 0x1)) {
const _0xc1b189 = await _0x46895d[_0x5ed43f(0x285)](getFinalVideo, _0x314f8e, _0xabb5ea, _0x533915);
if (_0x46895d[_0x5ed43f(0x3c2)](_0xc1b189, null))
return JSON[_0x5ed43f(0x3a2)](_0xc1b189);
}
if (_0x46895d[_0x5ed43f(0x334)](isVideoFormat, _0x533915)) {
const _0x2016c3 = {
'parse': 0x1,
'playUrl': '',
'url': _0x533915
};
return JSON[_0x5ed43f(0x3a2)](_0x2016c3);
} else {
const _0x59b4d5 = {
'parse': 0x1,
'jx': '1',
'url': _0x533915
};
return JSON[_0x5ed43f(0x3a2)](_0x59b4d5);
}
} catch (_0x15f170) {
SpiderDebug[_0x5ed43f(0x24a)](_0x15f170);
}
return '';
}
async function search(_0x15b8fa, _0x588e3d) {
const _0xc070a9 = _0x24a000, _0x24ff97 = {
'rAAqR': _0xc070a9(0x288),
'gHEas': _0xc070a9(0x2cf) + 'od',
'PPjsc': function (_0x4c022d, _0x4ebd2b) {
return _0x4c022d(_0x4ebd2b);
},
'nAAlp': function (_0x1196f9, _0x523142, _0x215206) {
return _0x1196f9(_0x523142, _0x215206);
},
'Yoody': function (_0x40a0f3, _0x527133, _0x5f956b) {
return _0x40a0f3(_0x527133, _0x5f956b);
},
'Qzbyi': function (_0xf70d91, _0x5d6ade) {
return _0xf70d91(_0x5d6ade);
},
'AhyMI': function (_0x42d25e, _0x371898) {
return _0x42d25e instanceof _0x371898;
},
'raJIH': function (_0x2a22fd, _0x2de3f5) {
return _0x2a22fd instanceof _0x2de3f5;
},
'bfaLF': function (_0x8207e7, _0x21fb6c) {
return _0x8207e7 !== _0x21fb6c;
}
};
try {
if (host[_0xc070a9(0x39f)](_0x24ff97[_0xc070a9(0x26f)]) || host[_0xc070a9(0x39f)](_0x24ff97[_0xc070a9(0x28c)])) {
const _0x26ec58 = host + (_0xc070a9(0x324) + _0xc070a9(0x28e)) + _0x24ff97[_0xc070a9(0x294)](encodeURIComponent, _0x15b8fa) + _0xc070a9(0x237), _0x1c1ca8 = await _0x24ff97[_0xc070a9(0x247)](request, _0x26ec58, _0x24ff97[_0xc070a9(0x294)](getHeaders, _0x26ec58)), _0xc6c488 = JSON[_0xc070a9(0x213)](_0x1c1ca8), _0x1ead5c = [];
if (_0xc6c488[_0xc070a9(0x394)] && Array[_0xc070a9(0x315)](_0xc6c488[_0xc070a9(0x394)]))
for (const _0x284ed3 of _0xc6c488[_0xc070a9(0x394)]) {
_0x1ead5c[_0xc070a9(0x332)]({
'vod_id': _0x284ed3[_0xc070a9(0x3c3)],
'vod_name': _0x284ed3[_0xc070a9(0x2b8)],
'vod_pic': _0x284ed3[_0xc070a9(0x290)] || '',
'vod_remarks': _0x284ed3[_0xc070a9(0x346) + 's'] || ''
});
}
return JSON[_0xc070a9(0x3a2)]({ 'list': _0x1ead5c });
} else {
const _0x4c1fc9 = host, _0x3631b2 = _0x24ff97[_0xc070a9(0x247)](getSearchUrl, _0x4c1fc9, _0x24ff97[_0xc070a9(0x294)](encodeURIComponent, _0x15b8fa)), _0x15e390 = await _0x24ff97[_0xc070a9(0x369)](request, _0x3631b2, _0x24ff97[_0xc070a9(0x2a1)](getHeaders, _0x3631b2)), _0x59d1cc = JSON[_0xc070a9(0x213)](_0x15e390);
let _0x136112 = null;
const _0x1337a6 = [];
if (_0x24ff97[_0xc070a9(0x3ac)](_0x59d1cc[_0xc070a9(0x394)], Array))
_0x136112 = _0x59d1cc[_0xc070a9(0x394)];
else {
if (_0x24ff97[_0xc070a9(0x2bc)](_0x59d1cc[_0xc070a9(0x339)], Object) && _0x24ff97[_0xc070a9(0x3ac)](_0x59d1cc[_0xc070a9(0x339)][_0xc070a9(0x394)], Array))
_0x136112 = _0x59d1cc[_0xc070a9(0x339)][_0xc070a9(0x394)];
else
_0x24ff97[_0xc070a9(0x2bc)](_0x59d1cc[_0xc070a9(0x339)], Array) && (_0x136112 = _0x59d1cc[_0xc070a9(0x339)]);
}
if (_0x24ff97[_0xc070a9(0x2ee)](_0x136112, null))
for (const _0x152e86 of _0x136112) {
if (_0x152e86[_0xc070a9(0x3c3)]) {
const _0x49ee8a = {
'vod_id': _0x152e86[_0xc070a9(0x3c3)],
'vod_name': _0x152e86[_0xc070a9(0x2b8)],
'vod_pic': _0x152e86[_0xc070a9(0x290)],
'vod_remarks': _0x152e86[_0xc070a9(0x346) + 's']
};
_0x1337a6[_0xc070a9(0x332)](_0x49ee8a);
} else {
const _0x467d07 = {
'vod_id': _0x152e86[_0xc070a9(0x3b6)],
'vod_name': _0x152e86[_0xc070a9(0x1e9)],
'vod_pic': _0x152e86[_0xc070a9(0x3ba)],
'vod_remarks': _0x152e86[_0xc070a9(0x258)]
};
_0x1337a6[_0xc070a9(0x332)](_0x467d07);
}
}
const _0x1e4c19 = { 'list': _0x1337a6 };
return JSON[_0xc070a9(0x3a2)](_0x1e4c19);
}
} catch (_0x334adf) {
SpiderDebug[_0xc070a9(0x24a)](_0x334adf);
}
return '';
}
async function getFinalVideo(_0x356707, _0x398327, _0x2ef122) {
const _0x12dc27 = _0x24a000, _0x44bf01 = {
'KPgHF': function (_0x55b24f, _0x2ecff3) {
return _0x55b24f === _0x2ecff3;
},
'WCCoT': function (_0x2ce219, _0x446505) {
return _0x2ce219 === _0x446505;
},
'QIbLN': _0x12dc27(0x1fb),
'XjiyL': function (_0x451dd4, _0x2b6510) {
return _0x451dd4 + _0x2b6510;
},
'eFJbi': function (_0xe7aa93, _0x51184b, _0x539572, _0x540f7d) {
return _0xe7aa93(_0x51184b, _0x539572, _0x540f7d);
},
'cchWu': function (_0x5d7821, _0x2a0a3c, _0x143221) {
return _0x5d7821(_0x2a0a3c, _0x143221);
},
'emPiw': function (_0x242abc, _0x178c18) {
return _0x242abc !== _0x178c18;
},
'HHlAe': _0x12dc27(0x366),
'snexY': _0x12dc27(0x2e3),
'oRses': _0x12dc27(0x352)
};
let _0xcd3790 = '';
for (const _0x5cb301 of _0x398327) {
if (_0x44bf01[_0x12dc27(0x200)](_0x5cb301, '') || _0x44bf01[_0x12dc27(0x205)](_0x5cb301, _0x44bf01[_0x12dc27(0x2a5)]))
continue;
const _0x2f83f6 = _0x44bf01[_0x12dc27(0x30c)](_0x5cb301, _0x2ef122), _0x4b7b47 = await _0x44bf01[_0x12dc27(0x219)](request, _0x2f83f6, null, -0x3 * 0x13f + -0x1 * 0x4d12 + 0x243 * 0x35);
let _0x5e80c0 = null;
try {
_0x5e80c0 = _0x44bf01[_0x12dc27(0x2c1)](jsonParse, _0x2ef122, _0x4b7b47);
} catch (_0x684857) {
}
if (_0x44bf01[_0x12dc27(0x2a3)](_0x5e80c0, null) && _0x5e80c0[_0x12dc27(0x3b3) + _0x12dc27(0x2f2)](_0x44bf01[_0x12dc27(0x364)]) && _0x5e80c0[_0x12dc27(0x3b3) + _0x12dc27(0x2f2)](_0x44bf01[_0x12dc27(0x3a7)]))
return _0x5e80c0[_0x12dc27(0x2e3)] = JSON[_0x12dc27(0x3a2)](_0x5e80c0[_0x12dc27(0x2e3)]), _0x5e80c0;
if (_0x4b7b47[_0x12dc27(0x39f)](_0x44bf01[_0x12dc27(0x2df)])) {
let _0x259a20 = ![];
for (const _0x4410e4 of htmlVideoKeyMatch) {
if (_0x4410e4[_0x12dc27(0x36e)](_0x4b7b47)) {
_0x259a20 = !![];
break;
}
}
_0x259a20 && (_0xcd3790 = _0x5cb301);
}
}
if (_0x44bf01[_0x12dc27(0x2a3)](_0xcd3790, '')) {
const _0x425204 = {
'parse': 0x0,
'playUrl': '',
'url': _0x2ef122
};
return JSON[_0x12dc27(0x3a2)](_0x425204);
}
return null;
}
function genPlayList(_0x2a68f0, _0x17eead, _0x2951b7, _0x47b9eb, _0x800257) {
const _0x1d5b05 = _0x24a000, _0x37e1eb = {
'qFCgy': _0x1d5b05(0x288),
'muyni': _0x1d5b05(0x2cf) + 'od',
'VdBFp': _0x1d5b05(0x27c) + 'p',
'fuavN': _0x1d5b05(0x25c),
'nqoHH': _0x1d5b05(0x343),
'TVfJB': function (_0x46f089, _0x2a240f) {
return _0x46f089 > _0x2a240f;
},
'Xavsg': _0x1d5b05(0x2c8)
}, _0x15a66c = [], _0x182550 = [];
if (_0x2a68f0[_0x1d5b05(0x39f)](_0x37e1eb[_0x1d5b05(0x37c)]) || _0x2a68f0[_0x1d5b05(0x39f)](_0x37e1eb[_0x1d5b05(0x383)])) {
const _0x40de27 = _0x17eead[_0x1d5b05(0x394)] && _0x17eead[_0x1d5b05(0x394)][-0x635 + 0x50e * -0x4 + -0x8cf * -0x3] ? _0x17eead[_0x1d5b05(0x394)][0x2 * 0x901 + -0x2382 + 0x1180] : {};
_0x47b9eb[_0x1d5b05(0x3c3)] = _0x40de27[_0x1d5b05(0x3c3)] || _0x800257, _0x47b9eb[_0x1d5b05(0x2b8)] = _0x40de27[_0x1d5b05(0x2b8)] || '', _0x47b9eb[_0x1d5b05(0x290)] = _0x40de27[_0x1d5b05(0x290)] || '', _0x47b9eb[_0x1d5b05(0x37d)] = _0x40de27[_0x1d5b05(0x37d)] || '', _0x47b9eb[_0x1d5b05(0x32c)] = _0x40de27[_0x1d5b05(0x32c)] || '', _0x47b9eb[_0x1d5b05(0x228)] = _0x40de27[_0x1d5b05(0x228)] || '', _0x47b9eb[_0x1d5b05(0x346) + 's'] = _0x40de27[_0x1d5b05(0x346) + 's'] || '', _0x47b9eb[_0x1d5b05(0x23d)] = _0x40de27[_0x1d5b05(0x23d)] || '', _0x47b9eb[_0x1d5b05(0x2cd) + 'or'] = _0x40de27[_0x1d5b05(0x2cd) + 'or'] || '', _0x47b9eb[_0x1d5b05(0x227) + 't'] = _0x40de27[_0x1d5b05(0x227) + 't'] || '', _0x47b9eb[_0x1d5b05(0x34d) + _0x1d5b05(0x3bf)] = _0x40de27[_0x1d5b05(0x34d) + _0x1d5b05(0x3bf)] || '', _0x47b9eb[_0x1d5b05(0x3a0) + 'rl'] = _0x40de27[_0x1d5b05(0x3a0) + 'rl'] || '';
return;
}
if (_0x2a68f0[_0x1d5b05(0x39f)](_0x37e1eb[_0x1d5b05(0x3a8)]) || _0x2a68f0[_0x1d5b05(0x39f)](_0x37e1eb[_0x1d5b05(0x238)])) {
const _0x249ca8 = _0x17eead[_0x1d5b05(0x339)] || {};
_0x47b9eb[_0x1d5b05(0x3c3)] = _0x249ca8[_0x1d5b05(0x3c3)] || _0x800257, _0x47b9eb[_0x1d5b05(0x2b8)] = _0x249ca8[_0x1d5b05(0x2b8)] || '', _0x47b9eb[_0x1d5b05(0x290)] = _0x249ca8[_0x1d5b05(0x290)] || '', _0x47b9eb[_0x1d5b05(0x37d)] = _0x249ca8[_0x1d5b05(0x311)] || '', _0x47b9eb[_0x1d5b05(0x32c)] = _0x249ca8[_0x1d5b05(0x32c)] || '', _0x47b9eb[_0x1d5b05(0x228)] = _0x249ca8[_0x1d5b05(0x228)] || '', _0x47b9eb[_0x1d5b05(0x346) + 's'] = _0x249ca8[_0x1d5b05(0x346) + 's'] || '', _0x47b9eb[_0x1d5b05(0x23d)] = _0x249ca8[_0x1d5b05(0x23d)] || '', _0x47b9eb[_0x1d5b05(0x2cd) + 'or'] = _0x249ca8[_0x1d5b05(0x2cd) + 'or'] || '', _0x47b9eb[_0x1d5b05(0x227) + 't'] = _0x249ca8[_0x1d5b05(0x227) + 't'] || '';
if (_0x249ca8[_0x1d5b05(0x225) + _0x1d5b05(0x251)] && Array[_0x1d5b05(0x315)](_0x249ca8[_0x1d5b05(0x225) + _0x1d5b05(0x251)]))
for (const _0x39d1e3 of _0x249ca8[_0x1d5b05(0x225) + _0x1d5b05(0x251)]) {
let _0x2f80cc = _0x39d1e3[_0x1d5b05(0x330)]?.[_0x1d5b05(0x314)]() || _0x39d1e3[_0x1d5b05(0x214)]?.[_0x1d5b05(0x314)]() || '';
if (!_0x2f80cc)
continue;
_0x182550[_0x1d5b05(0x332)](_0x2f80cc), _0x15a66c[_0x1d5b05(0x332)](_0x39d1e3[_0x1d5b05(0x366)] || '');
if (_0x39d1e3[_0x1d5b05(0x20d)]) {
const _0x2ff516 = parseUrlMap[_0x1d5b05(0x24f)](_0x2f80cc) || [];
!_0x2ff516[_0x1d5b05(0x39f)](_0x39d1e3[_0x1d5b05(0x20d)]) && _0x2ff516[_0x1d5b05(0x332)](_0x39d1e3[_0x1d5b05(0x20d)]), parseUrlMap[_0x1d5b05(0x396)](_0x2f80cc, _0x2ff516);
}
}
} else {
if (_0x2a68f0[_0x1d5b05(0x39f)](_0x37e1eb[_0x1d5b05(0x222)])) {
const _0x37e2c6 = _0x17eead[_0x1d5b05(0x339)] || {};
_0x47b9eb[_0x1d5b05(0x3c3)] = _0x37e2c6[_0x1d5b05(0x3c3)] || _0x800257, _0x47b9eb[_0x1d5b05(0x2b8)] = _0x37e2c6[_0x1d5b05(0x2b8)] || '', _0x47b9eb[_0x1d5b05(0x290)] = _0x37e2c6[_0x1d5b05(0x290)] || '', _0x47b9eb[_0x1d5b05(0x37d)] = _0x37e2c6[_0x1d5b05(0x311)] || '', _0x47b9eb[_0x1d5b05(0x32c)] = _0x37e2c6[_0x1d5b05(0x32c)] || '', _0x47b9eb[_0x1d5b05(0x228)] = _0x37e2c6[_0x1d5b05(0x228)] || '', _0x47b9eb[_0x1d5b05(0x346) + 's'] = _0x37e2c6[_0x1d5b05(0x346) + 's'] || '', _0x47b9eb[_0x1d5b05(0x23d)] = _0x37e2c6[_0x1d5b05(0x23d)] || '', _0x47b9eb[_0x1d5b05(0x2cd) + 'or'] = _0x37e2c6[_0x1d5b05(0x2cd) + 'or'] || '', _0x47b9eb[_0x1d5b05(0x227) + 't'] = _0x37e2c6[_0x1d5b05(0x227) + 't'] || '';
if (_0x37e2c6[_0x1d5b05(0x2f7) + _0x1d5b05(0x3a1)] && Array[_0x1d5b05(0x315)](_0x37e2c6[_0x1d5b05(0x2f7) + _0x1d5b05(0x3a1)]))
for (const _0x1f9806 of _0x37e2c6[_0x1d5b05(0x2f7) + _0x1d5b05(0x3a1)]) {
let _0x292c57 = _0x1f9806[_0x1d5b05(0x377) + 'o']?.[_0x1d5b05(0x3cb)]?.[_0x1d5b05(0x314)]() || _0x1f9806[_0x1d5b05(0x377) + 'o']?.[_0x1d5b05(0x211)]?.[_0x1d5b05(0x314)]() || '';
if (!_0x292c57)
continue;
_0x182550[_0x1d5b05(0x332)](_0x292c57), _0x15a66c[_0x1d5b05(0x332)](_0x1f9806[_0x1d5b05(0x366)] || '');
try {
const _0x4a4bc9 = parseUrlMap[_0x1d5b05(0x24f)](_0x292c57) || [];
if (_0x1f9806[_0x1d5b05(0x377) + 'o']?.[_0x1d5b05(0x213)]) {
const _0x3dac95 = _0x1f9806[_0x1d5b05(0x377) + 'o'][_0x1d5b05(0x213)][_0x1d5b05(0x265)](',');
_0x3dac95[_0x1d5b05(0x1e6)](_0x4dc07e => {
const _0x404f67 = _0x1d5b05;
_0x4dc07e && !_0x4a4bc9[_0x404f67(0x39f)](_0x4dc07e) && _0x4a4bc9[_0x404f67(0x332)](_0x4dc07e);
});
}
if (_0x1f9806[_0x1d5b05(0x377) + 'o']?.[_0x1d5b05(0x32d)]) {
const _0x57c8f0 = _0x1f9806[_0x1d5b05(0x377) + 'o'][_0x1d5b05(0x32d)][_0x1d5b05(0x265)](',');
_0x57c8f0[_0x1d5b05(0x1e6)](_0x522ba3 => {
const _0x5f1935 = _0x1d5b05;
_0x522ba3 && !_0x4a4bc9[_0x5f1935(0x39f)](_0x522ba3) && _0x4a4bc9[_0x5f1935(0x332)](_0x522ba3);
});
}
parseUrlMap[_0x1d5b05(0x396)](_0x292c57, _0x4a4bc9);
} catch (_0x35c48f) {
SpiderDebug[_0x1d5b05(0x24a)](_0x35c48f);
}
}
} else {
if (urlPattern1[_0x1d5b05(0x36e)](_0x2a68f0)) {
const _0x6e5bc5 = _0x17eead[_0x1d5b05(0x394)] && _0x17eead[_0x1d5b05(0x394)][0x1448 + -0x19fc + -0x1 * -0x5b4] ? _0x17eead[_0x1d5b05(0x394)][-0x704 * -0x5 + 0x29 * -0xb5 + -0x617 * 0x1] : {};
_0x47b9eb[_0x1d5b05(0x3c3)] = _0x6e5bc5[_0x1d5b05(0x3c3)] || _0x800257, _0x47b9eb[_0x1d5b05(0x2b8)] = _0x6e5bc5[_0x1d5b05(0x2b8)] || '', _0x47b9eb[_0x1d5b05(0x290)] = _0x6e5bc5[_0x1d5b05(0x290)] || '', _0x47b9eb[_0x1d5b05(0x37d)] = _0x6e5bc5[_0x1d5b05(0x37d)] || '', _0x47b9eb[_0x1d5b05(0x32c)] = _0x6e5bc5[_0x1d5b05(0x32c)] || '', _0x47b9eb[_0x1d5b05(0x228)] = _0x6e5bc5[_0x1d5b05(0x228)] || '', _0x47b9eb[_0x1d5b05(0x346) + 's'] = _0x6e5bc5[_0x1d5b05(0x346) + 's'] || '', _0x47b9eb[_0x1d5b05(0x23d)] = _0x6e5bc5[_0x1d5b05(0x23d)] || '', _0x47b9eb[_0x1d5b05(0x2cd) + 'or'] = _0x6e5bc5[_0x1d5b05(0x2cd) + 'or'] || '', _0x47b9eb[_0x1d5b05(0x227) + 't'] = _0x6e5bc5[_0x1d5b05(0x227) + 't'] || '', _0x47b9eb[_0x1d5b05(0x34d) + _0x1d5b05(0x3bf)] = _0x6e5bc5[_0x1d5b05(0x34d) + _0x1d5b05(0x3bf)] || '', _0x47b9eb[_0x1d5b05(0x3a0) + 'rl'] = _0x6e5bc5[_0x1d5b05(0x3a0) + 'rl'] || '';
}
}
}
_0x37e1eb[_0x1d5b05(0x30d)](_0x182550[_0x1d5b05(0x2d3)], -0x417 * 0x9 + -0x2472 + 0x186b * 0x3) && _0x37e1eb[_0x1d5b05(0x30d)](_0x15a66c[_0x1d5b05(0x2d3)], -0x1bc * 0x15 + -0x26b8 + 0x4b24) && (_0x47b9eb[_0x1d5b05(0x34d) + _0x1d5b05(0x3bf)] = _0x182550[_0x1d5b05(0x365)](_0x37e1eb[_0x1d5b05(0x2be)]), _0x47b9eb[_0x1d5b05(0x3a0) + 'rl'] = _0x15a66c[_0x1d5b05(0x365)](_0x37e1eb[_0x1d5b05(0x2be)]));
}
function jsonParse(_0x2bcad8, _0x2e7bc8) {
const _0x4a9b6b = _0x24a000, _0x54fefc = {
'glzca': _0x4a9b6b(0x339),
'SXiUp': function (_0x5d899b, _0x8ff4ce) {
return _0x5d899b === _0x8ff4ce;
},
'mqFNW': _0x4a9b6b(0x345),
'hXQXU': _0x4a9b6b(0x366),
'qaLZN': function (_0x304f89, _0x4f96a0) {
return _0x304f89 + _0x4f96a0;
},
'SyFuQ': _0x4a9b6b(0x1fd),
'wWTGM': _0x4a9b6b(0x292),
'opiXu': function (_0x16486e, _0x45288d) {
return _0x16486e(_0x45288d);
},
'GMucY': function (_0x55cf35, _0x5b1ec7, _0x56a7e3) {
return _0x55cf35(_0x5b1ec7, _0x56a7e3);
},
'VVWwW': _0x4a9b6b(0x2e3),
'zMWEf': _0x4a9b6b(0x310),
'fuDvD': _0x4a9b6b(0x255),
'AAtXX': _0x4a9b6b(0x39e),
'Ojjqt': _0x4a9b6b(0x2cb),
'rrjLd': _0x4a9b6b(0x261),
'xjYPA': function (_0x138833, _0x134ff4) {
return _0x138833 > _0x134ff4;
},
'UZCOD': _0x4a9b6b(0x2e4),
'PeDZZ': _0x4a9b6b(0x287),
'cCmOD': function (_0xe7c3fe, _0x6c71de) {
return _0xe7c3fe > _0x6c71de;
},
'clYHp': function (_0x34da34, _0x278ac6) {
return _0x34da34 + _0x278ac6;
},
'ZrFqI': function (_0x57a7fe, _0x1920c9, _0x45bdb2, _0x4ed88c) {
return _0x57a7fe(_0x1920c9, _0x45bdb2, _0x4ed88c);
}
};
try {
let _0x654842 = JSON[_0x4a9b6b(0x213)](_0x2e7bc8);
_0x654842[_0x4a9b6b(0x3b3) + _0x4a9b6b(0x2f2)](_0x54fefc[_0x4a9b6b(0x32f)]) && _0x54fefc[_0x4a9b6b(0x27d)](typeof _0x654842[_0x4a9b6b(0x339)], _0x54fefc[_0x4a9b6b(0x325)]) && !_0x654842[_0x4a9b6b(0x3b3) + _0x4a9b6b(0x2f2)](_0x54fefc[_0x4a9b6b(0x1e8)]) && (_0x654842 = _0x654842[_0x4a9b6b(0x339)]);
let _0x100c47 = _0x654842[_0x4a9b6b(0x366)];
_0x100c47[_0x4a9b6b(0x2c6)]('//') && (_0x100c47 = _0x54fefc[_0x4a9b6b(0x2eb)](_0x54fefc[_0x4a9b6b(0x245)], _0x100c47));
if (!_0x100c47[_0x4a9b6b(0x314)]()[_0x4a9b6b(0x2c6)](_0x54fefc[_0x4a9b6b(0x322)]))
return null;
if (_0x54fefc[_0x4a9b6b(0x27d)](_0x100c47, _0x2bcad8)) {
if (_0x54fefc[_0x4a9b6b(0x3b8)](isVip, _0x100c47) || !_0x54fefc[_0x4a9b6b(0x3b8)](isVideoFormat, _0x100c47))
return null;
}
if (_0x54fefc[_0x4a9b6b(0x22e)](isBlackVodUrl, _0x2bcad8, _0x100c47))
return null;
let _0xcda3cd = {};
if (_0x654842[_0x4a9b6b(0x3b3) + _0x4a9b6b(0x2f2)](_0x54fefc[_0x4a9b6b(0x224)]))
_0xcda3cd = _0x654842[_0x4a9b6b(0x2e3)];
else {
if (_0x654842[_0x4a9b6b(0x3b3) + _0x4a9b6b(0x2f2)](_0x54fefc[_0x4a9b6b(0x29e)]))
_0xcda3cd = _0x654842[_0x4a9b6b(0x310)];
else {
if (_0x654842[_0x4a9b6b(0x3b3) + _0x4a9b6b(0x2f2)](_0x54fefc[_0x4a9b6b(0x3ca)]))
_0xcda3cd = _0x654842[_0x4a9b6b(0x255)];
else
_0x654842[_0x4a9b6b(0x3b3) + _0x4a9b6b(0x2f2)](_0x54fefc[_0x4a9b6b(0x39a)]) && (_0xcda3cd = _0x654842[_0x4a9b6b(0x39e)]);
}
}
let _0x2e9070 = '';
if (_0x654842[_0x4a9b6b(0x3b3) + _0x4a9b6b(0x2f2)](_0x54fefc[_0x4a9b6b(0x3b9)]))
_0x2e9070 = _0x654842[_0x54fefc[_0x4a9b6b(0x3b9)]];
else
_0x654842[_0x4a9b6b(0x3b3) + _0x4a9b6b(0x2f2)](_0x54fefc[_0x4a9b6b(0x2a4)]) && (_0x2e9070 = _0x654842[_0x54fefc[_0x4a9b6b(0x2a4)]]);
_0x54fefc[_0x4a9b6b(0x25a)](_0x2e9070[_0x4a9b6b(0x314)]()[_0x4a9b6b(0x2d3)], -0x60f * 0x1 + 0x12 * -0x164 + 0x7 * 0x471) && (_0xcda3cd[_0x54fefc[_0x4a9b6b(0x2a4)]] = _0x54fefc[_0x4a9b6b(0x2eb)]('\x20', _0x2e9070));
let _0x530de6 = '';
if (_0x654842[_0x4a9b6b(0x3b3) + _0x4a9b6b(0x2f2)](_0x54fefc[_0x4a9b6b(0x297)]))
_0x530de6 = _0x654842[_0x4a9b6b(0x2e4)];
else
_0x654842[_0x4a9b6b(0x3b3) + _0x4a9b6b(0x2f2)](_0x54fefc[_0x4a9b6b(0x207)]) && (_0x530de6 = _0x654842[_0x4a9b6b(0x287)]);
_0x54fefc[_0x4a9b6b(0x281)](_0x530de6[_0x4a9b6b(0x314)]()[_0x4a9b6b(0x2d3)], 0x18ce + -0x22ae + 0x9e0) && (_0xcda3cd[_0x54fefc[_0x4a9b6b(0x207)]] = _0x54fefc[_0x4a9b6b(0x1f4)]('\x20', _0x530de6));
_0xcda3cd = _0x54fefc[_0x4a9b6b(0x243)](fixJsonVodHeader, _0xcda3cd, _0x2bcad8, _0x100c47);
const _0x27e9a5 = {
'header': _0xcda3cd,
'url': _0x100c47,
'parse': '0'
};
return _0x27e9a5;
} catch (_0x174821) {
SpiderDebug[_0x4a9b6b(0x24a)](_0x174821);
}
return null;
}
function isVip(_0x12df4f) {
const _0x1cd01d = _0x24a000, _0x2ec382 = {
'updKI': _0x1cd01d(0x2c9),
'XOpkJ': _0x1cd01d(0x3a6),
'iOaGQ': _0x1cd01d(0x306),
'uIZrh': _0x1cd01d(0x2f6),
'maOml': _0x1cd01d(0x21e),
'kJixo': _0x1cd01d(0x2a6),
'UgQzk': _0x1cd01d(0x31d),
'zyeHF': _0x1cd01d(0x22c),
'GPmSe': _0x1cd01d(0x282) + 'om',
'HIEhJ': _0x1cd01d(0x318) + 'm',
'SvZuD': _0x1cd01d(0x2fe),
'SaoFF': function (_0x49391c, _0x475da1) {
return _0x49391c < _0x475da1;
},
'dhhxf': function (_0x4f647c, _0x40da9b) {
return _0x4f647c === _0x40da9b;
},
'SSpmn': _0x1cd01d(0x3c9) + 'a_',
'SajNK': _0x1cd01d(0x3c9) + 'w_',
'IKQGq': _0x1cd01d(0x3c9) + 'v_'
};
try {
let _0x59a0c5 = ![];
const _0x472579 = new URL(_0x12df4f)[_0x1cd01d(0x3b4)], _0x39662c = [
_0x2ec382[_0x1cd01d(0x21c)],
_0x2ec382[_0x1cd01d(0x385)],
_0x2ec382[_0x1cd01d(0x38b)],
_0x2ec382[_0x1cd01d(0x34b)],
_0x2ec382[_0x1cd01d(0x2c0)],
_0x2ec382[_0x1cd01d(0x1f8)],
_0x2ec382[_0x1cd01d(0x26c)],
_0x2ec382[_0x1cd01d(0x2c3)],
_0x2ec382[_0x1cd01d(0x3c7)],
_0x2ec382[_0x1cd01d(0x2dd)],
_0x2ec382[_0x1cd01d(0x391)]
];
for (let _0x587e2f = 0x1168 * -0x1 + -0x2 * -0xffa + -0xe8c; _0x2ec382[_0x1cd01d(0x29f)](_0x587e2f, _0x39662c[_0x1cd01d(0x2d3)]); _0x587e2f++) {
if (_0x472579[_0x1cd01d(0x39f)](_0x39662c[_0x587e2f])) {
if (_0x2ec382[_0x1cd01d(0x358)](_0x39662c[_0x587e2f], _0x2ec382[_0x1cd01d(0x21c)])) {
if (_0x12df4f[_0x1cd01d(0x39f)](_0x2ec382[_0x1cd01d(0x267)]) || _0x12df4f[_0x1cd01d(0x39f)](_0x2ec382[_0x1cd01d(0x33a)]) || _0x12df4f[_0x1cd01d(0x39f)](_0x2ec382[_0x1cd01d(0x333)])) {
_0x59a0c5 = !![];
break;
}
} else {
_0x59a0c5 = !![];
break;
}
}
}
return _0x59a0c5;
} catch (_0x576cf8) {
SpiderDebug[_0x1cd01d(0x24a)](_0x576cf8);
}
return ![];
}
function isBlackVodUrl(_0x307605, _0x697c5d) {
const _0x4a2c61 = _0x24a000, _0x27d7bc = {
'gudMv': _0x4a2c61(0x2ad),
'FRrZt': _0x4a2c61(0x3be)
};
return _0x697c5d[_0x4a2c61(0x39f)](_0x27d7bc[_0x4a2c61(0x34c)]) || _0x697c5d[_0x4a2c61(0x39f)](_0x27d7bc[_0x4a2c61(0x210)]);
}
function fixJsonVodHeader(_0x194079, _0x3e179a, _0x56db4f) {
const _0x555e90 = _0x24a000, _0x3e9dd1 = {
'GlESc': function (_0x2d4a85, _0x14b753) {
return _0x2d4a85 === _0x14b753;
},
'dixTK': _0x555e90(0x2b1) + 'om',
'owLGb': _0x555e90(0x287),
'UKmVu': _0x555e90(0x261),
'wLZlp': _0x555e90(0x1fe) + '.0',
'yLRcH': _0x555e90(0x342),
'hhBdZ': _0x555e90(0x2f4),
'jIZRt': _0x555e90(0x2fb) + _0x555e90(0x2d6) + _0x555e90(0x22f),
'AQtGT': function (_0x35b12f, _0x2200a0) {
return _0x35b12f + _0x2200a0;
},
'tVGhB': _0x555e90(0x3b0) + _0x555e90(0x21d) + _0x555e90(0x2ae) + _0x555e90(0x26d) + _0x555e90(0x24e) + _0x555e90(0x37a) + _0x555e90(0x206) + _0x555e90(0x3c4) + _0x555e90(0x20e) + _0x555e90(0x360) + _0x555e90(0x38c) + _0x555e90(0x2e7)
};
_0x3e9dd1[_0x555e90(0x326)](_0x194079, null) && (_0x194079 = {});
if (_0x3e179a[_0x555e90(0x39f)](_0x3e9dd1[_0x555e90(0x260)]))
_0x194079[_0x3e9dd1[_0x555e90(0x1fc)]] = '\x20', _0x194079[_0x3e9dd1[_0x555e90(0x232)]] = _0x3e9dd1[_0x555e90(0x29b)];
else {
if (_0x56db4f[_0x555e90(0x39f)](_0x3e9dd1[_0x555e90(0x30b)]))
_0x194079[_0x3e9dd1[_0x555e90(0x1fc)]] = '\x20', _0x194079[_0x3e9dd1[_0x555e90(0x232)]] = _0x3e9dd1[_0x555e90(0x29b)];
else
_0x3e179a[_0x555e90(0x39f)](_0x3e9dd1[_0x555e90(0x27a)]) && (_0x194079[_0x3e9dd1[_0x555e90(0x1fc)]] = _0x3e9dd1[_0x555e90(0x209)], _0x194079[_0x3e9dd1[_0x555e90(0x232)]] = _0x3e9dd1[_0x555e90(0x335)]('\x20', _0x3e9dd1[_0x555e90(0x363)]));
}
return _0x194079;
}
const snifferMatch = /http((?!http).){26,}?\.(m3u8|mp4|flv|avi|mkv|rm|wmv|mpg)\?.*|http((?!http).){26,}\.(m3u8|mp4|flv|avi|mkv|rm|wmv|mpg)|http((?!http).){26,}\/m3u8\?pt=m3u8.*|http((?!http).)*?default\.ixigua\.com\/.*|http((?!http).)*?cdn-tos[^\?]*|http((?!http).)*?\/obj\/tos[^\?]*|http.*?\/player\/m3u8play\.php\?url=.*|http.*?\/player\/.*?[pP]lay\.php\?url=.*|http.*?\/playlist\/m3u8\/\?vid=.*|http.*?\.php\?type=m3u8&.*|http.*?\/download.aspx\?.*|http.*?\/api\/up_api.php\?.*|https.*?\.66yk\.cn.*|http((?!http).)*?netease\.com\/file\/.*/;
function isVideoFormat(_0x5515b3) {
const _0xf7bf44 = _0x24a000, _0x2fce53 = {
'HdgCs': _0xf7bf44(0x3b7),
'iPFTd': _0xf7bf44(0x1ef)
};
if (snifferMatch[_0xf7bf44(0x36e)](_0x5515b3))
return !_0x5515b3[_0xf7bf44(0x39f)](_0x2fce53[_0xf7bf44(0x309)]) || !_0x5515b3[_0xf7bf44(0x39f)](_0x2fce53[_0xf7bf44(0x1ee)]);
return ![];
}
function isVideo(_0x507319) {
const _0x1fc38a = _0x24a000, _0x2030df = {
'zjKSG': _0x1fc38a(0x350),
'omoGP': _0x1fc38a(0x35c)
};
return !_0x507319[_0x1fc38a(0x39f)](_0x2030df[_0x1fc38a(0x357)]) && !_0x507319[_0x1fc38a(0x39f)](_0x2030df[_0x1fc38a(0x248)]);
}
function UA(_0x59c882) {
const _0x1c26ca = _0x24a000, _0x800c4e = {
'KVRHH': _0x1c26ca(0x343),
'FVRLu': _0x1c26ca(0x286) + '.0',
'dZwJv': _0x1c26ca(0x3b0) + _0x1c26ca(0x21d) + _0x1c26ca(0x2ae) + _0x1c26ca(0x26d) + _0x1c26ca(0x24e) + _0x1c26ca(0x37a) + _0x1c26ca(0x206) + _0x1c26ca(0x3c4) + _0x1c26ca(0x20e) + _0x1c26ca(0x360) + _0x1c26ca(0x38c) + _0x1c26ca(0x2e7)
};
if (_0x59c882[_0x1c26ca(0x39f)](_0x800c4e[_0x1c26ca(0x289)]))
return _0x800c4e[_0x1c26ca(0x39c)];
return _0x800c4e[_0x1c26ca(0x305)];
}
function getCateUrl(_0x23db0c) {
const _0x49974e = _0x24a000, _0x37953d = {
'ECjej': _0x49974e(0x27c) + 'p',
'sFIgg': _0x49974e(0x25c),
'TJcyc': function (_0xdc8f68, _0x11b1f5) {
return _0xdc8f68 + _0x11b1f5;
},
'BxtWY': _0x49974e(0x2c4),
'tMugk': _0x49974e(0x343),
'YouNd': function (_0x4b91da, _0x11cfe1) {
return _0x4b91da + _0x11cfe1;
},
'GRdgl': _0x49974e(0x367)
};
if (_0x23db0c[_0x49974e(0x39f)](_0x37953d[_0x49974e(0x2d0)]) || _0x23db0c[_0x49974e(0x39f)](_0x37953d[_0x49974e(0x29c)]))
return _0x37953d[_0x49974e(0x235)](_0x23db0c, _0x37953d[_0x49974e(0x33c)]);
else
return _0x23db0c[_0x49974e(0x39f)](_0x37953d[_0x49974e(0x32e)]) ? _0x37953d[_0x49974e(0x236)](_0x23db0c, _0x37953d[_0x49974e(0x381)]) : '';
}
function getPlayUrlPrefix(_0x5ee424) {
const _0x1bf8f8 = _0x24a000, _0x598264 = {
'FSokj': _0x1bf8f8(0x27c) + 'p',
'FPdLA': _0x1bf8f8(0x25c),
'JQGUp': function (_0xdfc607, _0x448366) {
return _0xdfc607 + _0x448366;
},
'ToKis': _0x1bf8f8(0x348) + _0x1bf8f8(0x2a7),
'NaZIK': _0x1bf8f8(0x343),
'hggTv': function (_0x4737db, _0x8a0e91) {
return _0x4737db + _0x8a0e91;
},
'rcDwJ': _0x1bf8f8(0x30f) + _0x1bf8f8(0x22b)
};
if (_0x5ee424[_0x1bf8f8(0x39f)](_0x598264[_0x1bf8f8(0x323)]) || _0x5ee424[_0x1bf8f8(0x39f)](_0x598264[_0x1bf8f8(0x2a2)]))
return _0x598264[_0x1bf8f8(0x299)](_0x5ee424, _0x598264[_0x1bf8f8(0x3b5)]);
else
return _0x5ee424[_0x1bf8f8(0x39f)](_0x598264[_0x1bf8f8(0x21b)]) ? _0x598264[_0x1bf8f8(0x2de)](_0x5ee424, _0x598264[_0x1bf8f8(0x398)]) : '';
}
function getRecommendUrl(_0x80e8f1) {
const _0x43bed3 = _0x24a000, _0x5b36fd = {
'TOllB': _0x43bed3(0x27c) + 'p',
'PVTeb': _0x43bed3(0x25c),
'zyflE': function (_0x5b4b9d, _0x36c3c2) {
return _0x5b4b9d + _0x36c3c2;
},
'ijImY': _0x43bed3(0x268) + _0x43bed3(0x31b),
'EfLao': _0x43bed3(0x343),
'Sebfw': function (_0x1c1df5, _0x470f1b) {
return _0x1c1df5 + _0x470f1b;
},
'SdUcg': _0x43bed3(0x291)
};
if (_0x80e8f1[_0x43bed3(0x39f)](_0x5b36fd[_0x43bed3(0x354)]) || _0x80e8f1[_0x43bed3(0x39f)](_0x5b36fd[_0x43bed3(0x2ca)]))
return _0x5b36fd[_0x43bed3(0x2b0)](_0x80e8f1, _0x5b36fd[_0x43bed3(0x336)]);
else
return _0x80e8f1[_0x43bed3(0x39f)](_0x5b36fd[_0x43bed3(0x23b)]) ? _0x5b36fd[_0x43bed3(0x3b1)](_0x80e8f1, _0x5b36fd[_0x43bed3(0x2b4)]) : '';
}
function _0x30bd() {
const _0x2b0aa4 = [
'Rhngk',
'0\x20(Macinto',
'nqoHH',
'Udbgi',
'VVWwW',
'vod_url_wi',
'comic+4K=m',
'vod_conten',
'vod_area',
'bkKAx',
'分类+全部=+电影=',
'd_id=',
'acfun.cn',
'分类接口错误:',
'GMucY',
'i.com/',
'?ac=detail',
'hQLKD',
'UKmVu',
'Uqurg',
'11bSKqkq',
'TJcyc',
'YouNd',
'&pg=1',
'fuavN',
'Zelfl',
'+2008+2007',
'EfLao',
'limit',
'vod_actor',
'XhjKd',
'ist&t=',
'gINFD',
'?ac=list&z',
'匪+犯罪+动画+奇幻',
'ZrFqI',
'sh;\x20Intel\x20',
'SyFuQ',
'6057730KXKKrO',
'nAAlp',
'omoGP',
'+2024+2023',
'log',
'zlCKO',
'?type=',
'10ifJwJp',
')\x20AppleWeb',
'get',
'?wd=',
'th_player',
'nDVeB',
'MJeua',
'nFrDW',
'headers',
'area',
'tvplay+综艺=',
'state',
'indexOf',
'xjYPA',
'lass=',
'xgapp',
'search?tex',
'mWrNJ',
'axNZh',
'dixTK',
'User-Agent',
'eXwPu',
'pg=#PN#',
'ome/91.0.4',
'split',
'AdIkD',
'SSpmn',
'index_vide',
'okhttp/3.1',
'+2016+2015',
'&page=#PN#',
'UgQzk',
'Win64;\x20x64',
'RZVZb',
'rAAqR',
'FMcfW',
'qhbab',
'qvaVO',
'fBrnR',
'ts+评分=scor',
'vqyhb',
'uUBbz',
'SKgeb',
'tvshow+动漫=',
'FEuLQ',
'hhBdZ',
'lang',
'api.php/ap',
'SXiUp',
'rQSdz',
'OdHdL',
'bkfnv',
'cCmOD',
'bilibili.c',
'uzruO',
'+2006+2005',
'AEWJN',
'okhttp/4.1',
'Referer',
'/vod',
'KVRHH',
'大+其他\x0a筛选yea',
'fcPwA',
'gHEas',
'rfYvZ',
'ist&wd=',
'KqkGD',
'vod_pic',
'/vodPhbAll',
'http',
'UlRrv',
'PPjsc',
'9IUFsEu',
'+2012+2011',
'UZCOD',
'xVjfI',
'JQGUp',
'WodPN',
'wLZlp',
'sFIgg',
'+大陆+香港+台湾+',
'zMWEf',
'SaoFF',
'qrmQn',
'Qzbyi',
'FPdLA',
'emPiw',
'rrjLd',
'QIbLN',
'mgtv.com',
'il?id=',
'ovie_4k+体育',
'HHuLq',
'+农村+惊悚+惊悚+',
'=tiyu\x0a筛选cl',
'vod_list',
'973973.xyz',
'\x20NT\x2010.0;\x20',
'=1&area=&t',
'zyflE',
'www.mgtv.c',
'+2000',
'IWfGL',
'SdUcg',
'科幻+剧情+战争+警',
'umjti',
'+2018+2017',
'vod_name',
'eCaVc',
'nvSRb',
'fkHDy',
'raJIH',
'&pg=',
'Xavsg',
'xaxYD',
'maOml',
'cchWu',
'class&star',
'zyeHF',
'nav?token=',
'wovvt',
'startsWith',
'VeDky',
'$$$',
'iqiyi.com',
'PVTeb',
'user-agent',
'lpEGG',
'vod_direct',
'pagecount',
'/provide/v',
'ECjej',
'https://ji',
'OIKvw',
'length',
'vlist',
'fari/537.3',
'ww.bilibil',
'ea&type=筛选',
'Mac\x20OS\x20X\x201',
'QDURc',
'伦理+情色+福利+三',
'y=c87681c9',
'筛选area&lan',
'HIEhJ',
'hggTv',
'oRses',
'+爱情+恐怖+动作+',
'2.11',
'jIVVu',
'header',
'referer',
'replace',
'video?tid=',
'37.36',
'YTcha',
'type_exten',
'筛选area+全部=',
'qaLZN',
'3d5e430cac',
'znjdK',
'bfaLF',
'IKCWR',
'g=筛选lang&y',
'QZvys',
'erty',
'fIzpG',
'bilibili',
'4oTuTQS',
'le.com',
'vod_play_l',
'zMZmQ',
'class',
'472.114\x20Sa',
'\x20https://w',
'it=18&page',
'PzBoQ',
'pptv.com',
'JpyoV',
'GGHOc',
'OvREh',
'AsjQf',
'UwOqb',
'1aa5&url=',
'dZwJv',
'youku.com',
'ofHAn',
'ulXQF',
'HdgCs',
'HUsMa',
'yLRcH',
'XjiyL',
'TVfJB',
'zFyTh',
'/detail?vo',
'Header',
'vod_class',
'+2010+2009',
'IFEDw',
'trim',
'isArray',
'eXDqH',
'TmtUN',
'baofeng.co',
'KRVeJ',
'537.36\x20(KH',
'o?token=',
'IpeiC',
'sohu.com',
'wpdZs',
'+2014+2013',
'rDTqC',
'WNSZb',
'wWTGM',
'FSokj',
'?ac=videol',
'mqFNW',
'GlESc',
'EsiSO',
'fUjyK',
'+2002+2001',
'ghVBe',
'mEBLG',
'vod_year',
'parse2',
'tMugk',
'glzca',
'code',
'+2022+2021',
'push',
'IKQGq',
'ViinS',
'AQtGT',
'ijImY',
'host',
'ext',
'data',
'SajNK',
'MAPTF',
'BxtWY',
'floor',
'xIeyb',
'fmHZd',
'ear=筛选year',
'exi.jdyx.p',
'titan.mgtv',
'.vod',
'hPgPi',
'object',
'vod_remark',
'MWcjN',
'video_deta',
'ro/api/?ke',
'11069064LnYXCB',
'uIZrh',
'gudMv',
'vod_play_f',
'VoCNI',
'美国+英国+法国+日',
'.mp4',
'stype',
'<html',
'substring',
'TOllB',
'year',
'+武侠+冒险+枪战+',
'zjKSG',
'dhhxf',
'EeHWO',
'UqvHM',
'time+最热=hi',
'.m3u8',
'280463TzKcwD',
'dftSy',
'ZuLFK',
'.0.4472.12',
'ype=&start',
'XhSQM',
'tVGhB',
'HHlAe',
'join',
'url',
'/types',
'eRIpS',
'Yoody',
'mSlqf',
'lass&area=',
'影+古装+历史+运动',
'+印度+西班牙+加拿',
'test',
'number',
'r+全部=+2025',
'xIbro',
'CWGYP',
'&limit=18&',
'&ids=',
'qFHgN',
'keys',
'player_inf',
'TYodq',
'=#PN#',
'Kit/537.36',
'TML,\x20like\x20',
'qFCgy',
'type_name',
'yCXuy',
'WpxrU',
'fESQm',
'GRdgl',
'movie&page',
'muyni',
'+2020+2019',
'XOpkJ',
'&area=筛选ar',
'+全部=+',
'totalpage',
'amdth',
'sVWid',
'iOaGQ',
'4\x20Safari/5',
'ldHaK',
'IvNmw',
'yKQXX',
'+2004+2003',
'SvZuD',
'vgGfV',
'LtQsE',
'list',
'ePAKK',
'set',
'YmXhB',
'rcDwJ',
'total',
'AAtXX',
'典+青春+文艺+微电',
'FVRLu',
'xUxPS',
'Headers',
'includes',
'vod_play_u',
'ist',
'stringify',
'排序+全部=+最新=',
't=筛选year',
'movie+连续剧=',
'v.qq.com',
'snexY',
'VdBFp',
'rVGaG',
'VpQHj',
'PhMDd',
'AhyMI',
'1810774KTwiyo',
'iZers',
'0_15_7)\x20Ap',
'Mozilla/5.',
'Sebfw',
'nQbvl',
'hasOwnProp',
'hostname',
'ToKis',
'nextlink',
'cdn-tos',
'opiXu',
'Ojjqt',
'pic',
'vuXnk',
'TSUgZ',
'4391967FAEkgj',
'.fit:',
'rom',
'IkIJp',
'18PgCvfM',
'Knznh',
'vod_id',
'ike\x20Gecko)',
'type_id',
'iiExg',
'GPmSe',
'ist&t=1&pg',
'iqiyi.com/',
'fuDvD',
'from',
'VYHXK',
'nHBFf',
'jBTDy',
'3217345tuaNYa',
'forEach',
'恐怖+悬疑+惊悚+经',
'hXQXU',
'title',
'VKbJM',
'级+儿童+网络电影\x0a',
'BIDOf',
'lcxHY',
'iPFTd',
'.js',
'CrXgk',
'bgAzg',
'ass+全部=+喜剧',
'QPVjy',
'clYHp',
'&class=筛选c',
'skey',
'pksWn',
'kJixo',
'Gecko)\x20Chr',
'&page=',
'null',
'owLGb',
'https:',
'\x20Mozilla/5',
'本+韩国+德国+泰国',
'KPgHF',
'KitoD',
'filters',
'pleWebKit/',
'wRtKU',
'WCCoT',
'\x20(KHTML,\x20l',
'PeDZZ',
'UhViA',
'jIZRt',
'xAftd',
'NthFz',
'YfnZq',
'parse_api',
'\x20Chrome/91',
'RvYlw',
'FRrZt',
'show',
'KltAz',
'parse',
'name',
'value',
'?ac=list&c',
'content',
'd351f00e83',
'eFJbi',
'&by=排序&lim',
'NaZIK',
'updKI',
'0\x20(Windows',
'tudou.com',
'36490200zFFXUy'
];
_0x30bd = function () {
return _0x2b0aa4;
};
return _0x30bd();
}
function _0x3bf3(_0x57863f, _0x6af7ec) {
const _0x5c1083 = _0x30bd();
return _0x3bf3 = function (_0x20a234, _0x96f7f4) {
_0x20a234 = _0x20a234 - (0x17 * -0x157 + 0x1726 + 0x98e * 0x1);
let _0xf191c3 = _0x5c1083[_0x20a234];
return _0xf191c3;
}, _0x3bf3(_0x57863f, _0x6af7ec);
}
function getFilterTypes(_0x5a6e13, _0x2b8f18) {
const _0x3bda2f = _0x24a000, _0x23b59c = {
'JpyoV': function (_0x35c539, _0x252050) {
return _0x35c539 !== _0x252050;
},
'xIeyb': function (_0x58ea17, _0x3b5352) {
return _0x58ea17 === _0x3b5352;
},
'yCXuy': _0x3bda2f(0x2f9),
'lcxHY': _0x3bda2f(0x256),
'lpEGG': function (_0x23bff1, _0x3f2179) {
return _0x23bff1 === _0x3f2179;
},
'jIVVu': _0x3bda2f(0x27b),
'Rhngk': _0x3bda2f(0x355),
'GGHOc': function (_0x521589, _0x297d02) {
return _0x521589 + _0x297d02;
},
'xVjfI': function (_0x3f3091, _0x4aeb74) {
return _0x3f3091 + _0x4aeb74;
},
'uzruO': function (_0x5d7d7c, _0xe98ef2) {
return _0x5d7d7c + _0xe98ef2;
},
'amdth': _0x3bda2f(0x387),
'qvaVO': _0x3bda2f(0x343),
'fkHDy': _0x3bda2f(0x3a3) + _0x3bda2f(0x35b) + _0x3bda2f(0x274) + 'e',
'UqvHM': _0x3bda2f(0x27c) + 'p',
'UhViA': _0x3bda2f(0x25c),
'wovvt': _0x3bda2f(0x22a) + _0x3bda2f(0x3a5) + _0x3bda2f(0x257) + _0x3bda2f(0x278) + _0x3bda2f(0x226) + _0x3bda2f(0x2a8) + _0x3bda2f(0x2ab) + _0x3bda2f(0x1f2) + _0x3bda2f(0x2e0) + _0x3bda2f(0x2b5) + _0x3bda2f(0x242) + _0x3bda2f(0x356) + _0x3bda2f(0x1e7) + _0x3bda2f(0x39b) + _0x3bda2f(0x36c) + _0x3bda2f(0x2aa) + _0x3bda2f(0x2da) + _0x3bda2f(0x1eb) + _0x3bda2f(0x2ea) + _0x3bda2f(0x29d) + _0x3bda2f(0x34f) + _0x3bda2f(0x1ff) + _0x3bda2f(0x36d) + _0x3bda2f(0x28a) + _0x3bda2f(0x370) + _0x3bda2f(0x249) + _0x3bda2f(0x331) + _0x3bda2f(0x384) + _0x3bda2f(0x2b7) + _0x3bda2f(0x26a) + _0x3bda2f(0x31f) + _0x3bda2f(0x296) + _0x3bda2f(0x312) + _0x3bda2f(0x23a) + _0x3bda2f(0x284) + _0x3bda2f(0x390) + _0x3bda2f(0x329) + _0x3bda2f(0x2b2)
};
let _0x478f92 = '';
if (_0x23b59c[_0x3bda2f(0x2ff)](_0x2b8f18, null))
for (let _0x15bccf in _0x2b8f18) {
if (_0x23b59c[_0x3bda2f(0x33e)](_0x15bccf, _0x23b59c[_0x3bda2f(0x37e)]) || _0x23b59c[_0x3bda2f(0x33e)](_0x15bccf, _0x23b59c[_0x3bda2f(0x1ed)]) || _0x23b59c[_0x3bda2f(0x2cc)](_0x15bccf, _0x23b59c[_0x3bda2f(0x2e2)]) || _0x23b59c[_0x3bda2f(0x33e)](_0x15bccf, _0x23b59c[_0x3bda2f(0x220)]))
try {
_0x478f92 += _0x23b59c[_0x3bda2f(0x300)](_0x23b59c[_0x3bda2f(0x298)](_0x23b59c[_0x3bda2f(0x283)](_0x23b59c[_0x3bda2f(0x300)]('筛选', _0x15bccf), _0x23b59c[_0x3bda2f(0x389)]), _0x2b8f18[_0x15bccf][_0x3bda2f(0x2e5)](/,/g, '+')), '\x0a');
} catch (_0x1d7e3a) {
}
}
if (_0x5a6e13[_0x3bda2f(0x39f)](_0x23b59c[_0x3bda2f(0x272)]))
_0x478f92 += _0x23b59c[_0x3bda2f(0x298)]('\x0a', _0x23b59c[_0x3bda2f(0x2bb)]);
else {
if (_0x5a6e13[_0x3bda2f(0x39f)](_0x23b59c[_0x3bda2f(0x35a)]) || _0x5a6e13[_0x3bda2f(0x39f)](_0x23b59c[_0x3bda2f(0x208)])) {
} else
_0x478f92 = _0x23b59c[_0x3bda2f(0x2c5)];
}
return _0x478f92;
}
function getCateFilterUrlSuffix(_0x43934c) {
const _0x85df30 = _0x24a000, _0x46e977 = {
'TYodq': _0x85df30(0x27c) + 'p',
'eXwPu': _0x85df30(0x25c),
'CWGYP': _0x85df30(0x1f5) + _0x85df30(0x36b) + _0x85df30(0x2dc) + _0x85df30(0x2f0) + _0x85df30(0x340) + _0x85df30(0x373) + _0x85df30(0x263),
'PzBoQ': _0x85df30(0x343),
'eXDqH': _0x85df30(0x1f5) + _0x85df30(0x36b) + _0x85df30(0x2dc) + _0x85df30(0x2f0) + _0x85df30(0x340) + _0x85df30(0x21a) + _0x85df30(0x2fc) + _0x85df30(0x379),
'ldHaK': _0x85df30(0x26b) + _0x85df30(0x386) + _0x85df30(0x2d7) + _0x85df30(0x2c2) + _0x85df30(0x3a4)
};
if (_0x43934c[_0x85df30(0x39f)](_0x46e977[_0x85df30(0x378)]) || _0x43934c[_0x85df30(0x39f)](_0x46e977[_0x85df30(0x262)]))
return _0x46e977[_0x85df30(0x372)];
else
return _0x43934c[_0x85df30(0x39f)](_0x46e977[_0x85df30(0x2fd)]) ? _0x46e977[_0x85df30(0x316)] : _0x46e977[_0x85df30(0x38d)];
}
function getCateFilterUrlPrefix(_0x4c93b0) {
const _0x3fffd5 = _0x24a000, _0x242566 = {
'UlRrv': _0x3fffd5(0x27c) + 'p',
'XhSQM': _0x3fffd5(0x25c),
'EsiSO': function (_0x42f55a, _0xb7ae1a) {
return _0x42f55a + _0xb7ae1a;
},
'hQLKD': _0x3fffd5(0x2e6),
'QPVjy': _0x3fffd5(0x343),
'VKbJM': function (_0x1ee890, _0x56d819) {
return _0x1ee890 + _0x56d819;
},
'rDTqC': _0x3fffd5(0x24c),
'KltAz': _0x3fffd5(0x216) + _0x3fffd5(0x25b)
};
if (_0x4c93b0[_0x3fffd5(0x39f)](_0x242566[_0x3fffd5(0x293)]) || _0x4c93b0[_0x3fffd5(0x39f)](_0x242566[_0x3fffd5(0x362)]))
return _0x242566[_0x3fffd5(0x327)](_0x4c93b0, _0x242566[_0x3fffd5(0x231)]);
else
return _0x4c93b0[_0x3fffd5(0x39f)](_0x242566[_0x3fffd5(0x1f3)]) ? _0x242566[_0x3fffd5(0x1ea)](_0x4c93b0, _0x242566[_0x3fffd5(0x320)]) : _0x242566[_0x3fffd5(0x1ea)](_0x4c93b0, _0x242566[_0x3fffd5(0x212)]);
}
function isBan(_0x559ee9) {
const _0x593d11 = _0x24a000, _0x1bf583 = {
'KqkGD': function (_0x392b7e, _0x3e9c56) {
return _0x392b7e === _0x3e9c56;
},
'qFHgN': function (_0x5bc06d, _0xd9c8b2) {
return _0x5bc06d === _0xd9c8b2;
},
'nHBFf': function (_0x5d5ccb, _0x92465a) {
return _0x5d5ccb === _0x92465a;
}
};
return _0x1bf583[_0x593d11(0x28f)](_0x559ee9, '伦理') || _0x1bf583[_0x593d11(0x375)](_0x559ee9, '情色') || _0x1bf583[_0x593d11(0x1e3)](_0x559ee9, '福利');
}
function getSearchUrl(_0x37d0e3, _0x2f490d) {
const _0x5e71d3 = _0x24a000, _0x17c124 = {
'iiExg': _0x5e71d3(0x343),
'ulXQF': function (_0x1c2f9a, _0x17943f) {
return _0x1c2f9a + _0x17943f;
},
'VoCNI': function (_0x80c03a, _0x241ab6) {
return _0x80c03a + _0x241ab6;
},
'IvNmw': _0x5e71d3(0x250),
'PhMDd': _0x5e71d3(0x1fa),
'sVWid': _0x5e71d3(0x27c) + 'p',
'AdIkD': _0x5e71d3(0x25c),
'rVGaG': _0x5e71d3(0x25d) + 't=',
'axNZh': _0x5e71d3(0x2bd),
'WNSZb': function (_0xe30936, _0x1a9baa) {
return _0xe30936 + _0x1a9baa;
},
'nDVeB': _0x5e71d3(0x241) + 'm='
};
if (_0x37d0e3[_0x5e71d3(0x39f)](_0x17c124[_0x5e71d3(0x3c6)]))
return _0x17c124[_0x5e71d3(0x308)](_0x17c124[_0x5e71d3(0x34e)](_0x17c124[_0x5e71d3(0x34e)](_0x37d0e3, _0x17c124[_0x5e71d3(0x38e)]), _0x2f490d), _0x17c124[_0x5e71d3(0x3ab)]);
else {
if (_0x37d0e3[_0x5e71d3(0x39f)](_0x17c124[_0x5e71d3(0x38a)]) || _0x37d0e3[_0x5e71d3(0x39f)](_0x17c124[_0x5e71d3(0x266)]))
return _0x17c124[_0x5e71d3(0x308)](_0x17c124[_0x5e71d3(0x34e)](_0x17c124[_0x5e71d3(0x34e)](_0x37d0e3, _0x17c124[_0x5e71d3(0x3a9)]), _0x2f490d), _0x17c124[_0x5e71d3(0x25f)]);
else {
if (urlPattern1[_0x5e71d3(0x36e)](_0x37d0e3))
return _0x17c124[_0x5e71d3(0x321)](_0x17c124[_0x5e71d3(0x308)](_0x17c124[_0x5e71d3(0x34e)](_0x37d0e3, _0x17c124[_0x5e71d3(0x252)]), _0x2f490d), _0x17c124[_0x5e71d3(0x3ab)]);
}
}
return '';
}
function findJsonArray(_0x2c154b, _0x4dc412, _0xe7aee) {
const _0x4dd129 = _0x24a000, _0x1bb544 = {
'vqyhb': function (_0xb64ed9, _0x4d11c7) {
return _0xb64ed9 === _0x4d11c7;
},
'UwOqb': _0x4dd129(0x345),
'VpQHj': function (_0x5b1b6f, _0x57fdc1) {
return _0x5b1b6f !== _0x57fdc1;
},
'fESQm': function (_0x488b96, _0x2ffe35, _0x2d214e, _0x3f9aed) {
return _0x488b96(_0x2ffe35, _0x2d214e, _0x3f9aed);
},
'RvYlw': function (_0x2e40a7, _0xece297) {
return _0x2e40a7 === _0xece297;
},
'CrXgk': function (_0x48a030, _0x1e10e3) {
return _0x48a030 !== _0x1e10e3;
}
};
Object[_0x4dd129(0x376)](_0x2c154b)[_0x4dd129(0x1e6)](_0x4410f9 => {
const _0x53867c = _0x4dd129, _0x8beb43 = {
'TSUgZ': function (_0x52410f, _0x64397c) {
const _0x2a0b08 = _0x3bf3;
return _0x1bb544[_0x2a0b08(0x275)](_0x52410f, _0x64397c);
},
'FMcfW': _0x1bb544[_0x53867c(0x303)],
'OvREh': function (_0x17e635, _0x1e79bc) {
const _0x2b8dff = _0x53867c;
return _0x1bb544[_0x2b8dff(0x3aa)](_0x17e635, _0x1e79bc);
},
'RZVZb': function (_0x2aff9c, _0x16add9, _0x39fb37, _0x56dec0) {
const _0x399614 = _0x53867c;
return _0x1bb544[_0x399614(0x380)](_0x2aff9c, _0x16add9, _0x39fb37, _0x56dec0);
}
};
try {
const _0x5b9b85 = _0x2c154b[_0x4410f9];
_0x1bb544[_0x53867c(0x20f)](_0x4410f9, _0x4dc412) && Array[_0x53867c(0x315)](_0x5b9b85) && _0xe7aee[_0x53867c(0x332)](_0x5b9b85), _0x1bb544[_0x53867c(0x20f)](typeof _0x5b9b85, _0x1bb544[_0x53867c(0x303)]) && _0x1bb544[_0x53867c(0x1f0)](_0x5b9b85, null) && (Array[_0x53867c(0x315)](_0x5b9b85) ? _0x5b9b85[_0x53867c(0x1e6)](_0xce021c => {
const _0x7a8860 = _0x53867c;
_0x8beb43[_0x7a8860(0x3bc)](typeof _0xce021c, _0x8beb43[_0x7a8860(0x270)]) && _0x8beb43[_0x7a8860(0x301)](_0xce021c, null) && _0x8beb43[_0x7a8860(0x26e)](findJsonArray, _0xce021c, _0x4dc412, _0xe7aee);
}) : _0x1bb544[_0x53867c(0x380)](findJsonArray, _0x5b9b85, _0x4dc412, _0xe7aee));
} catch (_0x161cd2) {
SpiderDebug[_0x53867c(0x24a)](_0x161cd2);
}
});
}
function jsonArr2Str(_0x2ac5a3) {
const _0x171e1b = _0x24a000, _0x3f6d96 = {
'IFEDw': function (_0x584b3a, _0x1079df) {
return _0x584b3a < _0x1079df;
}
}, _0x36becd = [];
for (let _0x29367c = -0x1 * -0x1987 + 0x1 * -0x1323 + -0x664; _0x3f6d96[_0x171e1b(0x313)](_0x29367c, _0x2ac5a3[_0x171e1b(0x2d3)]); _0x29367c++) {
try {
_0x36becd[_0x171e1b(0x332)](_0x2ac5a3[_0x29367c]);
} catch (_0x3e4b7e) {
SpiderDebug[_0x171e1b(0x24a)](_0x3e4b7e);
}
}
return _0x36becd[_0x171e1b(0x365)](',');
}
function getHeaders(_0x2dbbbb) {
const _0x690d7 = _0x24a000, _0x11947b = {
'OdHdL': _0x690d7(0x261),
'VeDky': function (_0x4325bb, _0x1c5140) {
return _0x4325bb(_0x1c5140);
}
}, _0x24e5fe = {};
return _0x24e5fe[_0x11947b[_0x690d7(0x27f)]] = _0x11947b[_0x690d7(0x2c7)](UA, _0x2dbbbb), _0x24e5fe;
}
function isJsonString(_0x52901c) {
const _0x44dab5 = _0x24a000;
try {
JSON[_0x44dab5(0x213)](_0x52901c);
} catch (_0x568d34) {
return ![];
}
return !![];
}
export function __jsEvalReturn() {
return {
'init': init,
'home': home,
'homeVod': homeVod,
'category': category,
'detail': detail,
'play': play,
'search': search
};
}
+1669
View File
@@ -0,0 +1,1669 @@
/*
@header({
searchable: 1,
filterable: 1,
quickSearch: 1,
title: '聚合短剧',
lang: 'cat'
})
*/
import { Crypto as CryptoJS } from 'assets://js/lib/cat.js';
let debug = 1;
let siteName = '聚合短剧';
let xingya_headers = {};
let niuniu_headers = {};
let niuniu_token = '';
let niuniu_access_token = '';
let hema_headers = {};
// 搜索缓存
const searchCache = new Map();
const CACHE_TTL = 5 * 60 * 1000;
// 分类排除规则
const cate_remove = ['分类排除', '软鸭', '碎片', '锦鲤', '番茄', '甜圈'];
const UA = "Mozilla/5.0 (Linux; Android 11; Pixel 5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.91 Mobile Safari/537.36";
const aggConfig = {
keys: 'd3dGiJc651gSQ8w1',
searchLimit: 20,
searchTimeout: 8000,
charMap: {
'+': 'P', '/': 'X', '0': 'M', '1': 'U', '2': 'l', '3': 'E', '4': 'r', '5': 'Y', '6': 'W', '7': 'b', '8': 'd', '9': 'J',
'A': '9', 'B': 's', 'C': 'a', 'D': 'I', 'E': '0', 'F': 'o', 'G': 'y', 'H': '_', 'I': 'H', 'J': 'G', 'K': 'i', 'L': 't',
'M': 'g', 'N': 'N', 'O': 'A', 'P': '8', 'Q': 'F', 'R': 'k', 'S': '3', 'T': 'h', 'U': 'f', 'V': 'R', 'W': 'q', 'X': 'C',
'Y': '4', 'Z': 'p', 'a': 'm', 'b': 'B', 'c': 'O', 'd': 'u', 'e': 'c', 'f': '6', 'g': 'K', 'h': 'x', 'i': '5', 'j': 'T',
'k': '-', 'l': '2', 'm': 'z', 'n': 'S', 'o': 'Z', 'p': '1', 'q': 'V', 'r': 'v', 's': 'j', 't': 'Q', 'u': '7', 'v': 'D',
'w': 'w', 'x': 'n', 'y': 'L', 'z': 'e'
},
headers: {
json: { 'User-Agent': 'okhttp/4.10.0', 'Content-Type': 'application/json' },
form: { 'User-Agent': 'okhttp/4.10.0', 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8' },
niuniu: { 'Cache-Control': 'no-cache', 'Content-Type': 'application/json;charset=UTF-8', 'User-Agent': 'okhttp/4.12.0' },
baidu: { 'Content-Type': 'application/x-www-form-urlencoded', 'User-Agent': UA },
hema: {
'datas': 'e5f22c6e2c82fe001738cb9ce4696eab0556d064a55aef402e0fbe6b29a083f6538e4567de38e67de2071a49d9751526bfba45314e1fd4702b11c76ab9a3b5f873262854ba66e6715ed51364dbc6ee62c7180e047fcbcdbfd49874fc8f28674b16d90ca71a02de76c70598e0b75e647c37c2c19287e49be5f2a259d727dfc4df3d28802388bf3c356576b342e17e30a2ab74859263dba4d1c8eba79990d22d60d60927fdacb2addf2f0eaadd8887585ca2eb87f603faf0c207dda18cf67dc25b2199d303baff9e6605b3314a7d2631f62864f48619daceb9452f2b7b0667773553741856df030cca68af3c57810f983d452bb428ef5fc32206aef4865ae06c629bee7f5135547304acc7ef4e7c6df887308f2e79c493fd2ee03488722861b5bb51b09cb8911dfc92c288d94e601c066d2f9d612ad2c8d4eeb4920b1d44aff3e13fd75229b857f64925df1cf12f75a00d438c422ec1726462b915903f1dd1f4bb7cdf82cc15a6d507f80c789903e710f39a62aef073f3f93a6c681e75d295428aa290d7e98f82e7e9ad6e2b23d9086dfe8c63c5d8550b13fd61a77291473a8bdd43c7c2639f264be69d9d07f0585de4342a399275a64e7d1d4400b8ed4421a2f289f622e40cdd1cfc916a0b9ce747c924ac33e32d24b91ed5d64772d6ad6896412f52724006eabf12aaecfd6e81dad432c7b3800bbf793a1c375e3e7b4fb3b097724b5fc88a8c9bcf3dbc10cbdb252965',
'Content-Type': 'text/plain'
},
haokan: {
'User-Agent': UA,
'Talos-Module-Name': 'shortDrama',
'Talos-Module-Version': '1.0.71.1',
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8',
'Cookie': 'BAIDUCUID=giHCu0azv80G8SfQ0avU8gaaH8jfiv86ju2MugiR2i8-k3a35avAa1_mA'
}
}
};
// ==================== URL配置 ====================
const rule = {
百度: {
host: 'https://mbd.baidu.com',
detailHost: 'https://sv.baidu.com',
list: '/feedapi/v1/videoserver/playlets/list?service=bdbox',
search: '/feedapi/v1/videoserver/playlets/search?service=bdbox',
detail: '/haokan/ui-video/playlet/rec/detail?log=vhk&tn=1020970b&ctn=1008350n&blur=1',
play: '/appui/api?cmd=video/relate&log=vhk&tn=1020970b&ctn=1008350n&blur=1'
},
七猫: {
host: 'https://api-store.qmplaylet.com',
list: '/api/v1/playlet/index',
detail: 'https://api-read.qmplaylet.com/player/api/v1/playlet/info',
search: '/api/v1/playlet/search'
},
星芽: {
host: 'https://app.whjzjx.cn',
list: '/cloud/v2/theater/home_page?theater_class_id',
detail: '/v2/theater_parent/detail',
search: '/v3/search',
login: 'https://u.shytkjgs.com/user/v1/account/login'
},
西饭: {
host: 'https://xifan-api-cn.youlishipin.com',
list: '/xifan/drama/portalPage',
detail: '/xifan/drama/getDuanjuInfo',
search: '/xifan/search/getSearchList'
},
牛牛: {
host: 'https://new.tianjinzhitongdaohe.com',
list: '/api/v1/app/screen/screenMovie',
detail: '/api/v1/app/play/movieDetails',
search: '/api/v1/app/search/searchMovie',
desc: '/api/v1/app/play/movieDesc',
visitor: '/api/v1/app/user/visitorInfo',
login: 'https://csj-sp.csjdeveloper.com/csj_sp/api/v1/user/login?siteid=5627189',
detail2: 'https://csj-sp.csjdeveloper.com/csj_sp/api/v1/shortplay/detail?siteid=5627189',
unlock: 'https://csj-sp.csjdeveloper.com/csj_sp/api/v1/pay/ad_unlock?siteid=5627189'
},
围观: {
host: 'https://api.drama.9ddm.com',
list: '/drama/home/shortVideoTags?version_code=1500&os_type=1',
detail: '/drama/home/shortVideoDetail?version_code=1500&os_type=1',
search: '/drama/home/search?version_code=1500&os_type=1'
},
河马: {
host: 'https://freevideo.zqqds.cn',
list: '/free-video-portal/portal/1121',
detail: '/free-video-portal/portal/1131',
episode: '/free-video-portal/portal/1132',
play: '/free-video-portal/portal/1133',
search: '/free-video-portal/portal/1803'
},
星星: {
host: 'http://read.api.duodutek.com',
list: '/novel-api/app/pageModel/getResourceById',
detail: '/novel-api/basedata/book/getChapterList'
},
好看: {
host: 'https://sv.baidu.com',
list: '/haokan/ui-feed/playletTagsFeed?osbranch=a0',
home: '/haokan/ui-feed/playletShelfFeed?osbranch=a0',
detail_list: '/appui/api?osbranch=a0',
detail: '/haokan/ui-video/playlet/rec/detail?osbranch=a0',
play: '/appui/api?osbranch=a0',
search: '/haokan/ui-interact/playlet/search/sugs?osbranch=a0'
}
};
const platformList = [
{ name: '百度短剧', id: '百度' },
{ name: '七猫短剧', id: '七猫' },
{ name: '星芽短剧', id: '星芽' },
{ name: '西饭短剧', id: '西饭' },
{ name: '牛牛短剧', id: '牛牛' },
{ name: '围观短剧', id: '围观' },
{ name: '河马短剧', id: '河马' },
{ name: '星星短剧', id: '星星' },
{ name: '好看短剧', id: '好看' }
];
const ruleFilterDef = {
百度: { area: '新剧' },
七猫: { area: '0' },
星芽: { area: '1' },
西饭: { area: '68@都市' },
牛牛: { area: '现言' },
围观: { area: '' },
河马: { area: '308' },
星星: { area: '1287' },
好看: { area: '1' }
};
// ==================== 筛选配置 ====================
const filterOptions = {
"七猫": [{
"key": "area",
"name": "分类",
"value": [
{ "n": "全部", "v": "" },
{ "n": "推荐", "v": "0" },
{ "n": "新剧", "v": "-1" },
{ "n": "都市情感", "v": "1273" },
{ "n": "古装", "v": "1272" },
{ "n": "都市", "v": "571" },
{ "n": "玄幻仙侠", "v": "1286" },
{ "n": "奇幻", "v": "570" },
{ "n": "乡村", "v": "590" },
{ "n": "民国", "v": "573" },
{ "n": "年代", "v": "572" },
{ "n": "青春校园", "v": "1288" },
{ "n": "武侠", "v": "371" },
{ "n": "科幻", "v": "594" },
{ "n": "末世", "v": "556" },
{ "n": "二次元", "v": "1289" },
{ "n": "逆袭", "v": "400" },
{ "n": "穿越", "v": "373" },
{ "n": "复仇", "v": "795" },
{ "n": "系统", "v": "787" },
{ "n": "权谋", "v": "790" },
{ "n": "重生", "v": "784" },
{ "n": "女性成长", "v": "1294" },
{ "n": "打脸虐渣", "v": "716" },
{ "n": "闪婚", "v": "480" },
{ "n": "强者回归", "v": "402" },
{ "n": "追妻火葬场", "v": "715" },
{ "n": "家庭", "v": "670" },
{ "n": "马甲", "v": "558" },
{ "n": "职场", "v": "724" },
{ "n": "宫斗", "v": "343" },
{ "n": "高手下山", "v": "1299" },
{ "n": "娱乐明星", "v": "1295" },
{ "n": "异能", "v": "727" },
{ "n": "宅斗", "v": "342" },
{ "n": "替身", "v": "712" },
{ "n": "穿书", "v": "338" },
{ "n": "商战", "v": "723" },
{ "n": "种田经商", "v": "1291" },
{ "n": "伦理", "v": "1293" },
{ "n": "社会话题", "v": "1290" },
{ "n": "致富", "v": "492" },
{ "n": "偷听心声", "v": "1258" },
{ "n": "脑洞", "v": "526" },
{ "n": "豪门总裁", "v": "624" },
{ "n": "萌宝", "v": "356" },
{ "n": "战神", "v": "527" },
{ "n": "真假千金", "v": "812" },
{ "n": "赘婿", "v": "36" },
{ "n": "神医", "v": "1269" },
{ "n": "神豪", "v": "37" },
{ "n": "小人物", "v": "1296" },
{ "n": "团宠", "v": "545" },
{ "n": "欢喜冤家", "v": "464" },
{ "n": "女帝", "v": "617" },
{ "n": "银发", "v": "1297" },
{ "n": "兵王", "v": "28" },
{ "n": "虐恋", "v": "16" },
{ "n": "甜宠", "v": "21" },
{ "n": "悬疑", "v": "27" },
{ "n": "搞笑", "v": "793" },
{ "n": "灵异", "v": "1287" }
]
}],
"牛牛": [{
"key": "area",
"name": "分类",
"value": [
{ "n": "全部", "v": "" },
{ "n": "现言", "v": "现言" },
{ "n": "古言", "v": "古言" },
{ "n": "历史", "v": "历史" },
{ "n": "都市", "v": "都市" },
{ "n": "活动", "v": "活动" },
{ "n": "逆袭", "v": "逆袭" },
{ "n": "豪门", "v": "豪门" },
{ "n": "现代言情", "v": "现代言情" },
{ "n": "战神", "v": "战神" },
{ "n": "甜宠", "v": "甜宠" },
{ "n": "穿越", "v": "穿越" },
{ "n": "古装", "v": "古装" },
{ "n": "虐心", "v": "虐心" },
{ "n": "神医", "v": "神医" },
{ "n": "赘婿", "v": "赘婿" },
{ "n": "亲情", "v": "亲情" },
{ "n": "复仇", "v": "复仇" },
{ "n": "玄幻", "v": "玄幻" },
{ "n": "古代言情", "v": "古代言情" },
{ "n": "热血", "v": "热血" },
{ "n": "动作", "v": "动作" },
{ "n": "喜剧", "v": "喜剧" },
{ "n": "悬疑", "v": "悬疑" },
{ "n": "军事", "v": "军事" },
{ "n": "二次元", "v": "二次元" },
{ "n": "未来", "v": "未来" },
{ "n": "快速穿越", "v": "快速穿越" },
{ "n": "烧脑", "v": "烧脑" },
{ "n": "治愈", "v": "治愈" },
{ "n": "其他剧情", "v": "其他剧情" }
]
}],
"百度": [{
"key": "area",
"name": "分类",
"value": [
{ "n": "新剧", "v": "新剧" },
{ "n": "限时免费", "v": "限时免费" },
{ "n": "精选", "v": "精选" },
{ "n": "独播", "v": "独播" },
{ "n": "全部", "v": "全部题材" },
{ "n": "神医", "v": "神医" },
{ "n": "连续剧", "v": "连续剧" },
{ "n": "都市", "v": "都市" },
{ "n": "现代言情", "v": "现代言情" },
{ "n": "异能", "v": "异能" },
{ "n": "逆袭", "v": "逆袭" },
{ "n": "甜宠", "v": "甜宠" },
{ "n": "总裁", "v": "总裁" },
{ "n": "萌宝", "v": "萌宝" },
{ "n": "战神", "v": "战神" },
{ "n": "宫斗宅斗", "v": "宫斗宅斗" },
{ "n": "神豪", "v": "神豪" },
{ "n": "虐恋", "v": "虐恋" },
{ "n": "闪婚", "v": "闪婚" },
{ "n": "玄幻", "v": "玄幻" },
{ "n": "穿越重生", "v": "穿越重生" },
{ "n": "年代", "v": "年代" },
{ "n": "家庭伦理", "v": "家庭伦理" },
{ "n": "古代言情", "v": "古代言情" },
{ "n": "武侠武打", "v": "武侠武打" },
{ "n": "赘婿", "v": "赘婿" },
{ "n": "单元剧", "v": "单元剧" },
{ "n": "青春校园", "v": "青春校园" },
{ "n": "历史架空", "v": "历史架空" },
{ "n": "王妃", "v": "王妃" },
{ "n": "鉴宝", "v": "鉴宝" },
{ "n": "科幻", "v": "科幻" },
{ "n": "军旅战争", "v": "军旅战争" },
{ "n": "种田", "v": "种田" }
]
}],
"围观": [{
"key": "area",
"name": "分类",
"value": [{ "n": "全部", "v": "" }]
}],
"星芽": [{
"key": "area",
"name": "分类",
"value": [
{ "n": "剧场", "v": "1" },
{ "n": "热播剧", "v": "2" },
{ "n": "会员专享", "v": "8" },
{ "n": "星选好剧", "v": "7" },
{ "n": "新剧", "v": "3" },
{ "n": "阳光剧场", "v": "5" }
]
}],
"西饭": [{
"key": "area",
"name": "分类",
"value": [
{ "n": "都市", "v": "68@都市" },
{ "n": "青春", "v": "68@青春" },
{ "n": "现代言情", "v": "81@现代言情" },
{ "n": "豪门", "v": "81@豪门" },
{ "n": "大女主", "v": "80@大女主" },
{ "n": "逆袭", "v": "79@逆袭" },
{ "n": "打脸虐渣", "v": "79@打脸虐渣" },
{ "n": "穿越", "v": "81@穿越" }
]
}],
"河马": [{
"key": "area",
"name": "分类",
"value": [
{ "n": "推荐", "v": "308" },
{ "n": "新剧", "v": "309" },
{ "n": "逆袭", "v": "310" },
{ "n": "恋爱", "v": "311" },
{ "n": "强者回归", "v": "312" },
{ "n": "豪门恩怨", "v": "313" },
{ "n": "古装", "v": "314" },
{ "n": "重生", "v": "315" },
{ "n": "萌宝", "v": "316" },
{ "n": "复仇", "v": "317" },
{ "n": "神医", "v": "318" },
{ "n": "高手下山", "v": "319" },
{ "n": "超能悬疑", "v": "320" },
{ "n": "传承觉醒", "v": "321" },
{ "n": "神豪", "v": "322" },
{ "n": "民国", "v": "323" }
]
}],
"星星": [{
"key": "area",
"name": "分类",
"value": [
{ "n": "甜宠", "v": "1287" },
{ "n": "逆袭", "v": "1288" },
{ "n": "热血", "v": "1289" },
{ "n": "现代", "v": "1290" },
{ "n": "古代", "v": "1291" }
]
}],
"好看": [{
"key": "area",
"name": "分类",
"value": [
{ "n": "热播剧", "v": "1" },
{ "n": "新剧", "v": "2" },
{ "n": "战神", "v": "1001" },
{ "n": "神豪", "v": "2001" },
{ "n": "神医", "v": "1002" },
{ "n": "甜宠", "v": "1007" },
{ "n": "赘婿", "v": "1003" },
{ "n": "穿越重生", "v": "2004" },
{ "n": "异能", "v": "2005" },
{ "n": "虐恋", "v": "1006" },
{ "n": "宫斗宅斗", "v": "2006" },
{ "n": "玄幻", "v": "2009" }
]
}]
};
// 河马分类标签映射
const hemaTagIds = {
"308": "", "309": "", "310": "417,473,474,464", "311": "462,466", "312": "476",
"313": "585,616", "314": "444,468", "315": "417,439,464,465", "316": "589",
"317": "416,439,463,465", "318": "438", "319": "417,474,464", "320": "439,442,443,445,465,470",
"321": "417,473,474,464", "322": "472,475,585", "323": "590"
};
// 西饭搜索固定session参数
const XIFAN_SESSION_PARAMS = 'session=eyJpbmZvIjp7InVpZCI6IiIsInJ0IjoiMTc0MDY2ODk4NiIsInVuIjoiT1BHX2U5ODQ4NTgzZmM4ZjQzZTJhZjc5ZTcxNjRmZTE5Y2JjIiwiZnQiOiIxNzQwNjY4OTg2In19&feedssession=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1dHlwIjowLCJidWlkIjoxNjM0MDU3ODE4OTgxNDk5OTA0LCJhdWQiOiJkcmFtYSIsInZlciI6MiwicmF0IjoxNzQwNjY4OTg2LCJ1bm0iOiJPUEdfZTk4NDg1ODNmYzhmNDNlMmFmNzllNzE2NGZlMTljYmMiLCJpZCI6ImVhZGE1NmEyZWEzYTE0YmMwMzE3ZDc2ZmVjODJjNzc3IiwiZXhwIjoxNzQxMjczNzg2LCJkYyI6ImJqaHQifQ.IwuI0gK077RF4G10JRxgxx4GCG502vR8Z0W9EV4kd-c';
// ==================== 日志函数 ====================
function log(level, tag, msg) {
if (!debug) return;
const prefix = { 0: '🔍', 1: '✅', 2: '⚠️', 3: '❌' }[level] || '📝';
console.log(`${prefix}${tag}${msg}`);
}
function logTime(start, label) {
if (!debug) return;
console.log(`⏱️【${label}】耗时: ${Date.now() - start}ms`);
}
// ==================== 七猫公共函数 ====================
async function getQmParamsAndSign() {
let sessionId = Math.floor(Date.now()).toString();
let data = {
"static_score": "0.8",
"uuid": "00000000-7fc7-08dc-0000-000000000000",
"device-id": "20250220125449b9b8cac84c2dd3d035c9052a2572f7dd0122edde3cc42a70",
"mac": "",
"sourceuid": "aa7de295aad621a6",
"refresh-type": "0",
"model": "22021211RC",
"wlb-imei": "",
"client-id": "aa7de295aad621a6",
"brand": "Redmi",
"oaid": "",
"oaid-no-cache": "",
"sys-ver": "12",
"trusted-id": "",
"phone-level": "H",
"imei": "",
"wlb-uid": "aa7de295aad621a6",
"session-id": sessionId
};
let jsonStr = JSON.stringify(data);
let base64Str = base64Encode(jsonStr).replace(/[\r\n\s]/g, '');
let qmParams = '';
for (let c of base64Str) qmParams += aggConfig.charMap[c] || c;
let paramsStr = `AUTHORIZATION=app-version=10001application-id=com.duoduo.readchannel=unknownis-white=net-env=5platform=androidqm-params=${qmParams}reg=${aggConfig.keys}`;
let sign = await md5(paramsStr);
log(0, '七猫', `qmParams生成成功`);
return { qmParams, sign };
}
async function getQiMaoHeaders() {
let { qmParams, sign } = await getQmParamsAndSign();
return {
'net-env': '5', 'reg': '', 'channel': 'unknown', 'is-white': '',
'platform': 'android', 'application-id': 'com.duoduo.read', 'AUTHORIZATION': '',
'app-version': '10001', 'user-agent': 'okhttp/4.10.0',
'qm-params': qmParams, 'sign': sign, 'Content-Type': 'application/json'
};
}
// ==================== 缓存管理 ====================
const loginCache = new Map();
const LOGIN_CACHE_TTL = 24 * 60 * 60 * 1000;
function generateDeviceId() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
let r = Math.random() * 16 | 0;
let v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
function getSearchCache(key) {
const cached = searchCache.get(key);
if (cached && Date.now() - cached.time < CACHE_TTL) {
log(0, '缓存', `命中: ${key}`);
return cached.data;
}
return null;
}
function setSearchCache(key, data) {
searchCache.set(key, { data, time: Date.now() });
}
// ==================== 初始化 ====================
async function init(cfg) {
const start = Date.now();
log(1, '初始化', `========== ${siteName} ==========`);
// 星芽登录
try {
const response = await request(rule.星芽.login, {
method: 'POST',
headers: { 'User-Agent': 'okhttp/4.10.0', 'platform': '1', 'Content-Type': 'application/json' },
data: { device: '24250683a3bdb3f118dff25ba4b1cba1a' }
});
const res = JSON.parse(response || '{}');
const token = res?.data?.token || res?.token || res?.access_token;
xingya_headers = token ? { ...aggConfig.headers.json, authorization: token } : aggConfig.headers.json;
log(token ? 1 : 2, '星芽', token ? `登录成功` : `登录失败`);
} catch (e) {
xingya_headers = aggConfig.headers.json;
log(2, '星芽', `异常: ${e.message}`);
}
// 牛牛初始化
const nnDeviceId = generateDeviceId();
log(0, '牛牛', `设备ID: ${nnDeviceId}`);
try {
let tkhtml = await request(rule.牛牛.host + rule.牛牛.visitor, {
method: 'GET',
headers: { "deviceid": nnDeviceId, "token": "", "User-Agent": "okhttp/4.12.0", "client": "app", "devicetype": "Android", "Content-Type": "application/json" }
});
let tkRes = JSON.parse(tkhtml || '{}');
niuniu_token = tkRes.data?.token || '';
log(niuniu_token ? 1 : 2, '牛牛', niuniu_token ? `访客token成功` : `访客token失败`);
niuniu_headers = { ...aggConfig.headers.niuniu, "token": niuniu_token, "deviceid": nnDeviceId };
} catch (e) {
log(2, '牛牛', `访客token异常: ${e.message}`);
niuniu_headers = { ...aggConfig.headers.niuniu, "deviceid": nnDeviceId };
}
// 牛牛广告解锁
try {
let t = String(Math.floor(Date.now() / 1000));
let body = `ac=wifi&os=Android&vod_version=1.10.21.6-tob&os_version=9&type=1&clientVersion=v5.2.5&uuid=Y4WNZ3SAWK7MAJMH7CXCDHJ4VMPVFRZQTBSIA4XTYO4AWEUHIK6Q01&resolution=1280*2618&openudid=889edced38f1069b&dt=Pixel%204&sha1=46121F77CE2FCAD3DBC3B9EC8A24908C1A8AD6D9&os_api=28&install_id=1549688030634536&device_brand=google&sdk_version=1.1.3.0&package_name=com.niuniu.ztdh.app&siteid=5627189&dev_log_aid=667431&oaid=&timestamp=${t}`;
let nonce = "VX1KKGtoBDCi1fB1";
let signature = hmacSHA256(t + nonce + body, 'aceaa47f96b4875d446b2e1d97e03bbb');
let encbdoy = aesEncryptECB(body, 'dafdb3d2a5c343d6');
let response = await request(rule.牛牛.login, {
method: "POST",
headers: { 'X-Salt': '786774955F', 'X-Nonce': nonce, 'X-Timestamp': t, 'X-Signature': signature, 'Content-Type': 'application/x-www-form-urlencoded', 'User-Agent': 'okhttp/4.10.0' },
data: encbdoy
});
if (response) {
let logindata = aesDecryptECB(response, 'dafdb3d2a5c343d6');
let accesstoken = JSON.parse(logindata || '{}');
niuniu_access_token = accesstoken.data?.access_token || '';
log(niuniu_access_token ? 1 : 2, '牛牛', niuniu_access_token ? `广告token成功` : `广告token失败`);
}
} catch (e) {
log(2, '牛牛', `广告解锁异常: ${e.message}`);
}
// 河马初始化
hema_headers = { ...aggConfig.headers.hema, 'User-Agent': 'okhttp/4.10.0' };
log(1, '河马', `初始化成功`);
logTime(start, 'init');
return true;
}
// ==================== 首页分类 ====================
function home(filter) {
const platForms = platformList.filter(item => !cate_remove.some(word => new RegExp(word, 'i').test(item.name)));
const classes = platForms.map(item => ({
type_name: item.name,
type_id: item.id,
type_flag: '[CFS][SUBSITE2][FILTERBAR]'
}));
const filters = {};
platForms.forEach(item => {
if (filterOptions[item.id]) filters[item.id] = filterOptions[item.id];
});
log(0, '首页', `分类数: ${classes.length}`);
return JSON.stringify({ class: classes, filters: filters });
}
// ==================== 首页推荐 ====================
async function homeVod() {
const start = Date.now();
const platForms = platformList.filter(item => !cate_remove.some(word => new RegExp(word, 'i').test(item.name)));
const randomPlat = platForms[Math.floor(Math.random() * platForms.length)];
const randomArea = ruleFilterDef[randomPlat.id]?.area || '';
const categoryResult = await category(randomPlat.id, 1, { area: randomArea }, {});
const categoryList = JSON.parse(categoryResult).list || [];
log(1, '首页推荐', `返回 ${categoryList.length}`);
logTime(start, 'homeVod');
return JSON.stringify({ list: categoryList });
}
// ==================== 分类列表 ====================
async function category(tid, pg, filter, extend) {
const start = Date.now();
const page = pg || 1;
const area = filter?.area || extend?.area || ruleFilterDef[tid]?.area || '';
const videos = [];
const platRule = rule[tid];
log(0, '分类', `${tid} page=${page} area=${area}`);
switch (tid) {
case '七猫': {
let params = { operation: 1, playlet_privacy: 1 };
if (area && area !== '0' && area !== '') params.tag_id = area;
if (page > 1) params.next_id = page;
const keys = Object.keys(params).sort();
let signStr = keys.map(k => `${k}=${params[k]}`).join('') + aggConfig.keys;
params.sign = await md5(signStr);
const url = `${platRule.host}${platRule.list}?${buildUrlQuery(params)}`;
const headers = await getQiMaoHeaders();
const response = await request(url, { method: 'GET', headers });
if (response) {
const res = JSON.parse(response);
const items = res.data?.list || [];
log(0, '七猫', `获取 ${items.length}`);
items.forEach(item => {
videos.push({
vod_id: `七猫@${encodeURIComponent(item.playlet_id)}`,
vod_name: item.title || '',
vod_pic: item.image_link || '',
vod_remarks: `七猫短剧 | ${item.total_episode_num || 0}`,
vod_content: item.tags || ''
});
});
}
break;
}
case '百度': {
let sub = ["新剧", "限时免费", "精选", "独播"].includes(area) ? area : "新剧";
let tcsub = area === "全部" || area === "全部题材" ? "" : area;
let t = Math.floor(Date.now() / 1000);
let version = await md5(t + "v2");
const postData = {
'data': JSON.stringify({
"data": {
"extRequest": { "flow_tabid": "13" },
"from": "feed",
"page": "channel_video_landing",
"pd": "feed",
"refreshIndex": parseInt(page),
"cursor": "",
"theme": "",
"timestamp": t,
"version": version,
"themes": [
{ "kind": "综合", "names": [sub] },
{ "kind": "题材", "names": [tcsub] }
]
}
})
};
let html = await request(`${platRule.host}${platRule.list}`, {
method: 'POST',
headers: aggConfig.headers.baidu,
data: postData
});
let res = JSON.parse(html);
let items = res.data?.items || [];
log(0, '百度', `获取 ${items.length}`);
items.slice(0, 20).forEach(it => {
videos.push({
vod_id: `百度@${it.collId}`,
vod_name: it.title || '未知短剧',
vod_pic: it.img || '',
vod_remarks: '百度短剧 | ' + (it.updateStatus || "更新中"),
vod_content: it.description || ''
});
});
break;
}
case '星芽': {
const url = `${platRule.host}${platRule.list}=${area}&type=1&class2_ids=0&page_num=${page}&page_size=24`;
const response = await request(url, { headers: xingya_headers });
const res = JSON.parse(response);
const items = res.data?.list || [];
log(0, '星芽', `获取 ${items.length}`);
items.forEach(it => {
videos.push({
vod_id: `星芽@${it.theater.id}`,
vod_name: it.theater.title || '',
vod_pic: it.theater.cover_url || '',
vod_remarks: '星芽短剧 | ' + (it.theater.total ? `${it.theater.total}` : ''),
vod_content: `播放量:${it.theater.play_amount_str || 0}`
});
});
break;
}
case '西饭': {
const [typeId, typeName] = area.split('@');
const ts = Math.floor(Date.now() / 1000);
const url = `${platRule.host}${platRule.list}?reqType=aggregationPage&offset=${(page - 1) * 30}&categoryId=${typeId}&quickEngineVersion=-1&scene=&categoryNames=${encodeURIComponent(typeName)}&categoryVersion=1&density=1.5&pageID=page_theater&version=2001001&androidVersionCode=28&requestId=${ts}aa498144140ef297&appId=drama&teenMode=false&userBaseMode=false&${XIFAN_SESSION_PARAMS}`;
const response = await request(url, { headers: aggConfig.headers.form });
const res = JSON.parse(response);
let count = 0;
(res.result?.elements || []).forEach(soup => {
(soup.contents || []).forEach(vod => {
const dj = vod.duanjuVo || {};
videos.push({
vod_id: `西饭@${dj.duanjuId}#${dj.source}`,
vod_name: dj.title || '',
vod_pic: dj.coverImageUrl || '',
vod_remarks: '西饭短剧 | ' + (dj.total ? `${dj.total}` : ''),
vod_content: dj.desc || ''
});
count++;
});
});
log(0, '西饭', `获取 ${count}`);
break;
}
case '牛牛': {
let condition = { "typeId": "S1" };
if (area && area !== '全部' && area !== '') condition.classify = area;
const postData = { "condition": condition, "pageNum": page, "pageSize": 24 };
const response = await request(`${platRule.host}${platRule.list}`, {
method: 'POST',
headers: niuniu_headers,
data: postData
});
const res = JSON.parse(response);
const items = res.data?.records || [];
log(0, '牛牛', `获取 ${items.length}`);
items.forEach(item => {
videos.push({
vod_id: `牛牛@${item.id}`,
vod_name: item.name || '',
vod_pic: item.cover || '',
vod_remarks: '牛牛短剧 | ' + (item.totalEpisode ? `${item.totalEpisode}` : ''),
vod_content: item.description || ''
});
});
break;
}
case '围观': {
const postData = { "audience": "全部受众", "page": page, "pageSize": 30, "searchWord": "", "subject": "全部主题" };
const response = await request(`${platRule.host}${platRule.search}`, {
method: 'POST',
headers: aggConfig.headers.json,
data: postData
});
const res = JSON.parse(response);
const items = (res.code === 200 && res.data) ? res.data : [];
log(0, '围观', `获取 ${items.length}`);
items.forEach(it => {
videos.push({
vod_id: `围观@${it.oneId}`,
vod_name: it.title || '未知短剧',
vod_pic: it.vertPoster || it.horizonPoster || '',
vod_remarks: '围观短剧 | ' + `集数:${it.episodeCount || 0}`,
vod_content: it.description || ''
});
});
break;
}
case '河马': {
try {
const sub = area || '308';
const tagIds = hemaTagIds[sub] || '';
const bodys = JSON.stringify({
"recSwitch": true, "channelId": sub, "tagIds": tagIds,
"cnxhFlag": page - 1, "playListFlag": true,
"watchRecords": ["41000103722_572752006"]
});
const body = hemaEncrypt(bodys);
const response = await request(`${platRule.host}${platRule.list}`, {
method: 'POST',
headers: { ...hema_headers, 'Content-Type': 'application/x-www-form-urlencoded' },
data: body
});
const res = JSON.parse(response);
const dehtml = res.data;
if (dehtml) {
const hmdata = hemaDecrypt(dehtml);
if (hmdata && hmdata !== '{}') {
const hmlist = JSON.parse(hmdata).columnData || [];
hmlist.forEach(videoDataArray => {
(videoDataArray.videoData || []).forEach(video => {
videos.push({
vod_id: `河马@${video.bookId}`,
vod_name: video.bookName || '',
vod_pic: video.coverWap || video.coverCutWap,
vod_remarks: `河马短剧 | 更新${video.updateNum || 0}`,
vod_content: video.introduction || ''
});
});
});
}
}
} catch (e) {
log(2, '河马', e.message);
}
break;
}
case '星星': {
const postData = {
"productId": "2a8c14d1-72e7-498b-af23-381028eb47c0",
"vestId": "2be070e0-c824-4d0e-a67a-8f688890cadb",
"channel": "oppo19", "osType": "android", "version": "20",
"token": "202509271001001446030204698626", "resourceId": area,
"pageNum": String(page), "pageSize": "20"
};
const response = await request(`${platRule.host}${platRule.list}`, {
method: 'GET', headers: aggConfig.headers.form, data: postData
});
try {
const res = JSON.parse(response);
const items = res.data?.datalist || [];
log(0, '星星', `获取 ${items.length}`);
items.forEach(vod => {
videos.push({
vod_id: `星星@${vod.id}@${encodeURIComponent(vod.introduction || '')}`,
vod_name: vod.name || '',
vod_pic: vod.icon || '',
vod_remarks: `星星短剧 | ${vod.heat || 0}万播放`,
vod_content: vod.introduction || ''
});
});
} catch (e) {
log(2, '星星', e.message);
}
break;
}
case '好看': {
const postData = { "tag_id": area, "rn": "20", "pn": page };
const response = await request(`${platRule.host}${platRule.list}`, {
method: 'POST', headers: aggConfig.headers.haokan, data: postData
});
try {
const res = JSON.parse(response);
const items = res.data?.list || [];
log(0, '好看', `获取 ${items.length}`);
items.forEach(item => {
videos.push({
vod_id: `好看@${item.playlet_id}`,
vod_name: item.playlet_title || '',
vod_pic: item.playlet_poster || '',
vod_remarks: `好看短剧 | ${item.episodes_num_text || ''}`,
vod_content: item.tags ? item.tags.join('·') : ''
});
});
} catch (e) {
log(2, '好看', e.message);
}
break;
}
}
log(1, '分类', `${tid} 返回 ${videos.length}`);
logTime(start, 'category');
return JSON.stringify({ list: videos, page, pagecount: page + 1, limit: videos.length, total: videos.length * (page + 1) });
}
// ==================== 详情 ====================
async function detail(id) {
const parts = id.split('@');
const platform = parts[0];
const did = parts.slice(1).join('@');
const platRule = rule[platform];
let vod = {};
log(0, '详情', `${platform} ${did.substring(0, 50)}`);
switch (platform) {
case '七猫': {
const didDecoded = decodeURIComponent(did);
const sign = await md5(`playlet_id=${didDecoded}${aggConfig.keys}`);
const url = `${platRule.detail}?playlet_id=${didDecoded}&sign=${sign}`;
const headers = await getQiMaoHeaders();
const response = await request(url, { method: 'GET', headers });
const data = JSON.parse(response || '{}').data || {};
vod = {
vod_id: id, vod_name: data.title || '未知标题',
vod_pic: data.image_link || '', vod_remarks: `${data.tags || ''} ${data.total_episode_num || 0}`,
vod_content: data.intro || '未知剧情', vod_play_from: '七猫短剧',
vod_play_url: (data.play_list || []).map(it => `${it.sort}$${it.video_url}`).join('#')
};
break;
}
case '百度': {
const postData = { "playlet_id": did, "vid": "undefined" };
let html = await request(`${platRule.detailHost}${platRule.detail}`, {
method: 'POST', headers: aggConfig.headers.baidu, data: postData
});
let res = JSON.parse(html);
let dthtml = res.data || {};
let vids = dthtml.vid_list || [];
let playArr = vids.map((vid, index) => `${index + 1}$${did}@${vid}`);
vod = {
vod_id: id, vod_name: dthtml.playlet_title || '未知短剧',
vod_pic: dthtml.playlet_poster || '',
vod_content: `热度值:${dthtml.hot_value || 0}\n题材:${dthtml.tag_text || ''}\n集数:${dthtml.episodes_num || 0}\n简介:${dthtml.description || ''}`,
vod_remarks: `${vids.length || 0}`, vod_play_from: "百度短剧",
vod_play_url: playArr.join('#')
};
break;
}
case '星芽': {
const detailUrl = `${platRule.host}${platRule.detail}?theater_parent_id=${did}`;
const response = await request(detailUrl, { headers: xingya_headers });
const res = JSON.parse(response);
if (res.code === 'ok' && res.data) {
const data = res.data;
const playUrls = (data.theaters || []).map(item => `${item.num}$${item.son_video_url}`).join('#');
vod = {
vod_id: id, vod_name: data.title || '未知剧名',
vod_pic: data.cover_url || '', vod_remarks: data.is_over === 2 ? '连载中' : '已完结',
vod_content: data.introduction || data.desc || '',
vod_play_from: '星芽短剧', vod_play_url: playUrls || '暂无播放地址$0'
};
}
break;
}
case '西饭': {
const [duanjuId, source] = did.split('#');
const url = `${platRule.host}${platRule.detail}?duanjuId=${duanjuId}&source=${source}`;
const response = await request(url, { headers: aggConfig.headers.form });
const res = JSON.parse(response);
const data = res.result || {};
const playUrls = (data.episodeList || []).map(ep => `${ep.index}$${ep.playUrl}`).join('#');
vod = {
vod_id: id, vod_name: data.title || '', vod_pic: data.coverImageUrl || '',
vod_content: data.desc || '未知',
vod_remarks: data.updateStatus === 'over' ? `${data.total || 0}集 已完结` : `更新${data.total || 0}`,
vod_play_from: '西饭短剧', vod_play_url: playUrls
};
break;
}
case '牛牛': {
const descData = await request(`${platRule.host}${platRule.desc}`, {
method: 'POST', headers: niuniu_headers, data: { "id": did, "typeId": "S1" }
});
const descRes = JSON.parse(descData);
const descInfo = descRes.data || {};
const listData = await request(`${platRule.host}${platRule.detail}`, {
method: 'POST', headers: niuniu_headers, data: { "id": did, "source": 0, "typeId": "S1", "userId": "546932" }
});
const listRes = JSON.parse(listData);
const listInfo = listRes.data || {};
let playUrls = '';
if (listInfo.url && listInfo.episodeList && listInfo.episodeList.length > 0) {
playUrls = (listInfo.episodeList || []).map(ep => `${ep.episode}$${did}+${ep.id}`).join('#');
} else if (listInfo.thirdPlayId) {
let thirdPlayId = listInfo.thirdPlayId;
let data1 = "not_include=0&lock_free=1&type=1&clientVersion=v5.2.5&uuid=6IDYUSASPQY5BBVACWQW3LLTPV4V7DE26UOCX5TZTVUGX4VUJNXQ01&resolution=1080*2320&openudid=82f4175d577a2939&dt=22021211RC&os_api=31&install_id=1496879012031075&sdk_version=1.1.3.0&siteid=5627189&dev_log_aid=667431&oaid=abec0dfff623201b&timestamp=1752498494&direction=0&ac=mobile&os=Android&vod_version=1.10.21.6-tob&os_version=12&count=1&index=1&shortplay_id=" + thirdPlayId + "&sha1=46121F77CE2FCAD3DBC3B9EC8A24908C1A8AD6D9&device_brand=Redmi&package_name=com.niuniu.ztdh.app";
try {
let html1 = await niuniuPost(rule.牛牛.detail2, data1, "1");
if (html1 && html1.data && html1.data.episode_right_list) {
playUrls = html1.data.episode_right_list.map(it => {
let lockType = it.lock_type || 'free';
return `${it.index}$${it.index}+${lockType}+${thirdPlayId}`;
}).join('#');
}
} catch (e) { log(2, '牛牛详情', e.message); }
}
vod = {
vod_id: id, vod_name: descInfo.name || listInfo.name || '未知名称',
vod_pic: descInfo.cover || listInfo.cover || '',
vod_content: `类型:${descInfo.classify || ''}\n评分:${descInfo.score || ''}\n简介:${descInfo.introduce || ''}`,
vod_remarks: `${descInfo.totalEpisode || listInfo.totalEpisode || 0}`,
vod_play_from: '牛牛短剧', vod_play_url: playUrls || '暂无播放地址$0'
};
break;
}
case '围观': {
const response = await request(`${platRule.host}${platRule.detail}&oneId=${did}&page=1&pageSize=1000`, {
headers: aggConfig.headers.form
});
const res = JSON.parse(response);
if (res.code === 200 && res.data) {
const data = res.data || [];
const firstEpisode = data[0] || {};
vod = {
vod_id: id, vod_name: firstEpisode.title || '',
vod_pic: firstEpisode.vertPoster || firstEpisode.horizonPoster || '',
vod_remarks: `${data.length || 0}`,
vod_content: `播放量:${firstEpisode.viewCount || 0} 收藏:${firstEpisode.collectionCount || 0} 评论:${firstEpisode.commentCount || 0}`,
vod_play_from: '围观短剧',
vod_play_url: data.map(ep => {
let playSetting = ep.playSetting || ep.videoClarityList || [];
try { if (typeof playSetting === 'string') playSetting = JSON.parse(playSetting); } catch (e) { }
const url = (playSetting.find(item => item.name === '1080P')?.url || playSetting.find(item => item.name === '720P')?.url || '');
return `${ep.playOrder || 1}$${url}`;
}).filter(ep => ep.split('$')[1]).join('#')
};
}
break;
}
case '河马': {
const bookId = did;
const body = hemaEncrypt(JSON.stringify({ "bookId": bookId }));
const detailResponse = await request(`${platRule.host}${platRule.detail}`, {
method: 'POST', headers: { ...hema_headers, 'Content-Type': 'application/x-www-form-urlencoded' }, data: body
});
const detailRes = JSON.parse(detailResponse);
const detailHtml = detailRes.data;
const postdata = hemaDecrypt(detailHtml);
const videoInfo = JSON.parse(postdata).videoInfo || {};
const episodeBody = hemaEncrypt(JSON.stringify({ "bookId": bookId, "chapterMin": videoInfo.updateNum || 0, "chapterMax": videoInfo.chapterIndex || 0 }));
const episodeResponse = await request(`${platRule.host}${platRule.episode}`, {
method: 'POST', headers: { ...hema_headers, 'Content-Type': 'application/x-www-form-urlencoded' }, data: episodeBody
});
const episodeRes = JSON.parse(episodeResponse);
const episodeHtml = episodeRes.data;
const playdata = hemaDecrypt(episodeHtml);
const chapterList = JSON.parse(playdata).chapterList || [];
const playUrls = chapterList.map(item => `${item.chapterName}$${item.chapterId}++${item.chapterIndex}++${bookId}`).join('#');
vod = {
vod_id: id, vod_name: videoInfo.bookName || '未知剧名',
vod_pic: videoInfo.coverWap, vod_remarks: videoInfo.finishStatusCn || `更新至${videoInfo.updateNum || 0}`,
vod_content: videoInfo.introduction || '暂无简介',
vod_play_from: '河马短剧', vod_play_url: playUrls || '暂无播放地址$0'
};
break;
}
case '星星': {
const partsArr = did.split('@');
const bookId = partsArr[0];
const contentDesc = decodeURIComponent(partsArr[1] || '');
const postData = {
"bookId": bookId, "productId": "2a8c14d1-72e7-498b-af23-381028eb47c0",
"vestId": "2be070e0-c824-4d0e-a67a-8f688890cadb", "channel": "oppo19",
"osType": "android", "version": "20", "token": "202509271001001446030204698626"
};
const response = await request(`${platRule.host}${platRule.detail}`, {
method: 'GET', headers: aggConfig.headers.form, data: postData
});
try {
const res = JSON.parse(response);
const data = res.data || [];
const playUrls = data.map((vodItem, index) => {
const playUrl = vodItem.shortPlayList?.[0]?.chapterShortPlayVoList?.[0]?.shortPlayUrl || '';
return playUrl ? `${index + 1}$${playUrl}` : null;
}).filter(Boolean).join('#');
vod = { vod_id: id, vod_name: '星星短剧', vod_content: contentDesc, vod_play_from: '星星短剧', vod_play_url: playUrls || '暂无播放地址$0' };
} catch (e) { log(2, '星星详情', e.message); }
break;
}
case '好看': {
const commonlistId = Date.now().toString().substring(0, 13);
const innerParams = `enable_enter_playlet=0&seek_time=0&hotspot=0&auto_show_hot_point_panel=0&type=playlet&commonlist_id=${commonlistId}&scene=&vid=&enable_atlas=0&mark_pn=&uk=&ctime=0&from=playlet_new&id=${did}&rn=10&pn=1&direction=3`;
const listResponse = await request(`${platRule.host}${platRule.detail_list}`, {
method: 'POST', headers: aggConfig.headers.haokan, data: { "video/commonlist": innerParams }
});
try {
const resObj = JSON.parse(listResponse);
const firstVideo = resObj['video/commonlist']?.data?.results?.[0];
const vid = firstVideo?.content?.vid;
const detailResponse = await request(`${platRule.host}${platRule.detail}`, {
method: 'POST', headers: aggConfig.headers.haokan, data: { "vid": vid, "playlet_id": did }
});
const detailDataObj = JSON.parse(detailResponse).data || {};
let vidList = detailDataObj.vid_list || [];
if (vidList.length === 0 && detailDataObj.results) vidList = detailDataObj.results.map(item => item.vid);
const playList = vidList.map((v, i) => `${i + 1}$${did}@${v}`).join('#');
vod = {
vod_id: id, vod_name: detailDataObj.playlet_title || '', vod_pic: detailDataObj.playlet_poster || '',
vod_remarks: (detailDataObj.hot_value || '') + '播放·' + (detailDataObj.episodes_num || '') + '集',
vod_content: detailDataObj.description || '', vod_play_from: '好看短剧', vod_play_url: playList
};
} catch (e) { log(2, '好看详情', e.message); }
break;
}
}
return JSON.stringify({ list: [vod] });
}
// ==================== 搜索 ====================
// ==================== 搜索 ====================
async function cfs(siteId, wd, pg) {
const start = Date.now();
const page = pg || 1;
const searchLimit = aggConfig.searchLimit;
const searchTimeout = aggConfig.searchTimeout;
let results = [];
const cacheKey = `${siteId}_${wd}_${page}`;
const cachedResult = getSearchCache(cacheKey);
if (cachedResult) {
return cachedResult;
}
log(0, '搜索', `${siteId} 关键词: ${wd}, 页码: ${page}`);
const platformItem = platformList.find(p => p.id === siteId);
if (platformItem && cate_remove.some(word => new RegExp(word, 'i').test(platformItem.name))) {
log(2, '搜索', `跳过平台: ${siteId}`);
return JSON.stringify({ list: [], page, pagecount: page + 1, limit: 0, total: 0 });
}
const platRule = rule[siteId];
switch (siteId) {
case '百度': {
const requestUrl = `${platRule.host}${platRule.search}`;
const postData = {
"data": {
"query": wd,
"page": page,
"attribute": ["title"],
"fe_page_type": "search",
"extra": {
"tab_id": "216",
"flow_tabid": "13",
"shortplay_source": "feed",
"from": "feed",
"tab_type": "搜索",
"sub_template": "playlet_search_result"
}
}
};
let html = await request(requestUrl, {
method: 'POST',
headers: aggConfig.headers.baidu,
data: postData,
timeout: searchTimeout
});
let res = JSON.parse(html);
let items = res.data?.itemList || res.data?.data?.itemList || res.itemList || res.data?.list || res.list || [];
log(0, '百度搜索', `获取到 ${items.length}`);
results = items.map(it => ({
vod_id: `百度@${it.nid?.split("_")[1] || it.collId || ''}`,
vod_name: it.title || '未知短剧',
vod_pic: it.img || '',
vod_remarks: '百度短剧 | ' + (it.collNum || it.updateStatus || "搜索短剧"),
vod_content: it.description || ''
}));
break;
}
case '七猫': {
try {
const trackId = 'ec1280db127955061754851657967';
let signString = `extend=page=${page}read_preference=0track_id=${trackId}wd=${wd}${aggConfig.keys}`;
let sign = await md5(signString);
const encodedKey = encodeURIComponent(wd);
const url = `${platRule.host}${platRule.search}?extend=&page=${page}&wd=${encodedKey}&read_preference=0&track_id=${trackId}&sign=${sign}`;
const headers = await getQiMaoHeaders();
const response = await request(url, { method: 'GET', headers, timeout: searchTimeout });
const res = JSON.parse(response || '{}');
let items = res.data?.list || res.list || [];
log(0, '七猫搜索', `获取到 ${items.length}`);
results = items.map(item => ({
vod_id: `七猫@${encodeURIComponent(item.playlet_id || item.id || '')}`,
vod_name: item.title || '未知标题',
vod_pic: item.image_link || item.cover || '',
vod_remarks: '七猫短剧 | ' + (item.tags || '') + ' ' + (item.total_episode_num ? `${item.total_episode_num}` : ''),
vod_content: item.intro || ''
}));
} catch (e) {
log(2, '七猫搜索', e.message);
}
break;
}
case '星芽': {
const postData = { "text": wd };
const requestUrl = `${platRule.host}${platRule.search}`;
const response = await request(requestUrl, {
method: 'POST',
headers: xingya_headers,
data: postData,
timeout: searchTimeout
});
const res = JSON.parse(response || '{}');
const items = res.data?.theater?.search_data || [];
log(0, '星芽搜索', `获取到 ${items.length}`);
results = items.map(item => ({
vod_id: `星芽@${item.id}`,
vod_name: item.title || '',
vod_pic: item.cover_url || '',
vod_remarks: '星芽短剧 | ' + (item.total ? `${item.total}` : ''),
vod_content: item.introduction || ''
}));
break;
}
case '西饭': {
const ts = Math.floor(Date.now() / 1000);
const url = `${platRule.host}${platRule.search}?keyword=${encodeURIComponent(wd)}&pageIndex=${page}&version=2001001&androidVersionCode=28&requestId=${ts}ea3a14bc0317d76f&appId=drama&teenMode=false&userBaseMode=false&${XIFAN_SESSION_PARAMS}`;
const response = await request(url, { headers: aggConfig.headers.form, timeout: searchTimeout });
const res = JSON.parse(response || '{}');
let items = [];
if (res.result?.elements) {
res.result.elements.forEach(soup => {
if (soup.contents) {
soup.contents.forEach(vod => {
const dj = vod.duanjuVo || {};
items.push({
vod_id: `西饭@${dj.duanjuId || ''}#${dj.source || ''}`,
vod_name: dj.title || '未知标题',
vod_pic: dj.coverImageUrl || '',
vod_remarks: '西饭短剧 | ' + (dj.total ? `${dj.total}` : ''),
vod_content: ''
});
});
}
});
}
log(0, '西饭搜索', `获取到 ${items.length}`);
results = items;
break;
}
case '牛牛': {
const postData = {
"condition": { "typeId": "S1", "value": wd },
"pageNum": page,
"pageSize": searchLimit
};
const response = await request(`${platRule.host}${platRule.search}`, {
method: 'POST',
headers: niuniu_headers,
data: postData,
timeout: searchTimeout
});
const res = JSON.parse(response || '{}');
const items = res.data?.records || [];
log(0, '牛牛搜索', `获取到 ${items.length}`);
results = items.map(item => ({
vod_id: `牛牛@${item.id}`,
vod_name: item.name || '',
vod_pic: item.cover || '',
vod_remarks: '牛牛短剧 | ' + (item.totalEpisode ? `${item.totalEpisode}` : ''),
vod_content: ''
}));
break;
}
case '围观': {
const postData = {
"audience": "",
"page": page,
"pageSize": 30,
"searchWord": wd,
"subject": ""
};
const response = await request(`${platRule.host}${platRule.search}`, {
method: 'POST',
headers: aggConfig.headers.json,
data: postData,
timeout: searchTimeout
});
const res = JSON.parse(response || '{}');
const items = (res.code === 200 && res.data) ? res.data : [];
log(0, '围观搜索', `获取到 ${items.length}`);
results = items.map(it => ({
vod_id: `围观@${it.oneId || ''}`,
vod_name: it.title || '未知标题',
vod_pic: it.vertPoster || it.horizonPoster || '',
vod_remarks: '围观短剧 | 集数:' + (it.episodeCount || 0),
vod_content: it.description || ''
}));
break;
}
case '河马': {
try {
const hmbody = JSON.stringify({
"keyword": wd,
"page": page,
"size": searchLimit
});
const encryptedBody = hemaEncrypt(hmbody);
const response = await request(`${platRule.host}${platRule.search}`, {
method: 'POST',
headers: hema_headers,
data: encryptedBody,
timeout: searchTimeout
});
const res = JSON.parse(response || '{}');
const xmres = res.data;
if (xmres) {
const dexmres = hemaDecrypt(xmres);
if (dexmres && dexmres !== '{}') {
const xmlist = JSON.parse(dexmres).searchVos || [];
log(0, '河马搜索', `获取到 ${xmlist.length}`);
results = xmlist.map(video => ({
vod_id: `河马@${video.bookId}`,
vod_name: video.bookName || '',
vod_pic: (video.coverWap || '') + '@Referer=',
vod_remarks: `河马短剧 | 共${video.updateNum || 0}`,
vod_content: video.introduction || ''
}));
}
}
} catch (e) {
log(2, '河马搜索', e.message);
}
break;
}
case '星星': {
try {
const postData = {
"productId": "2a8c14d1-72e7-498b-af23-381028eb47c0",
"vestId": "2be070e0-c824-4d0e-a67a-8f688890cadb",
"channel": "oppo19",
"osType": "android",
"version": "20",
"token": "202509271001001446030204698626",
"keyWord": wd,
"pageNum": String(page),
"pageSize": String(searchLimit)
};
const response = await request(`${platRule.host}${platRule.search}`, {
method: 'GET',
headers: aggConfig.headers.json,
data: postData,
timeout: searchTimeout
});
const res = JSON.parse(response || '{}');
const items = res.data?.datalist || [];
log(0, '星星搜索', `获取到 ${items.length}`);
results = items.map(vod => ({
vod_id: `星星@${vod.id}@${encodeURIComponent(vod.introduction || '')}`,
vod_name: vod.name || '',
vod_pic: vod.icon || '',
vod_remarks: `星星短剧 | ${vod.heat || 0}万播放`,
vod_content: vod.introduction || ''
}));
} catch (e) {
log(2, '星星搜索', e.message);
}
break;
}
case '好看': {
try {
const postData = { "search_word": wd };
const response = await request(`${platRule.host}${platRule.search}`, {
method: 'POST',
headers: aggConfig.headers.haokan,
data: postData,
timeout: searchTimeout
});
const res = JSON.parse(response || '{}');
const items = res.data || [];
log(0, '好看搜索', `获取到 ${items.length}`);
results = items.map(item => ({
vod_id: `好看@${item.id}`,
vod_name: item.title || '',
vod_pic: item.cover_url || '',
vod_remarks: '好看短剧 | ' + (item.tag ? item.tag.replace(/\//g, '·') : ''),
vod_content: ''
}));
} catch (e) {
log(2, '好看搜索', e.message);
}
break;
}
}
// 关键词过滤
const keywordRegex = new RegExp(wd, "i");
let filteredResults = [];
for (let item of results) {
if (item.vod_name && keywordRegex.test(item.vod_name)) {
filteredResults.push(item);
}
}
log(0, `${siteId}搜索`, `原始 ${results.length} 条,匹配后 ${filteredResults.length}`);
logTime(start, 'cfs');
const resultJson = JSON.stringify({
list: filteredResults,
page: page,
pagecount: page + 1,
limit: filteredResults.length,
total: filteredResults.length * (page + 1)
});
setSearchCache(cacheKey, resultJson);
return resultJson;
}
// ==================== 全局搜索 ====================
async function search(wd, quick, pg) {
const start = Date.now();
const videos = [];
const page = pg || 1;
log(1, '全局搜索', `关键词: ${wd}, 页码: ${page}`);
const platForms = platformList.filter(item => !cate_remove.some(word => new RegExp(word, 'i').test(item.name)));
log(0, '全局搜索', `${platForms.length} 个平台待搜索`);
const searchPromises = platForms.map(async (platform) => {
try {
const result = await cfs(platform.id, wd, page);
return JSON.parse(result).list || [];
} catch (e) {
log(2, '全局搜索', `${platform.id} 异常: ${e.message}`);
return [];
}
});
const searchResults = await Promise.all(searchPromises);
let totalResults = 0;
const hasResultPlats = [];
const noResultPlats = [];
searchResults.forEach((list, idx) => {
const platform = platForms[idx];
const count = list.length;
totalResults += count;
if (count > 0) {
hasResultPlats.push(`${platform.name}(${count}条)`);
} else {
noResultPlats.push(platform.name);
}
videos.push(...list);
});
if (hasResultPlats.length > 0) {
log(1, '搜索结果', `有结果: ${hasResultPlats.join(', ')}`);
} else {
log(2, '搜索结果', `无结果`);
}
if (noResultPlats.length > 0) {
log(2, '搜索结果', `无结果平台: ${noResultPlats.join(', ')}`);
}
log(1, '搜索结果汇总', `${totalResults}`);
// 关键词过滤
const keywordRegex = new RegExp(wd, "i");
let filteredResults = [];
for (let item of videos) {
if (item.vod_name && keywordRegex.test(item.vod_name)) {
filteredResults.push(item);
}
}
log(1, '全局搜索', `原始 ${videos.length} 条,过滤后 ${filteredResults.length}`);
logTime(start, 'search');
return JSON.stringify({
list: filteredResults,
page: page,
pagecount: page + 1,
limit: filteredResults.length,
total: filteredResults.length * (page + 1)
});
}
// ==================== 播放 ====================
async function play(flag, id, flags) {
log(0, '播放', `${flag} ${id.substring(0, 50)}`);
if (/好看|百度/.test(flag)) {
let parts = id.split('@');
let playletId = parts[0];
let vid = parts[1];
if (/好看/.test(flag)) {
const innerParams = `method=post&vid=${vid}&immersive_mode=v4_5&tplname=feed_small_video&tag=playlet_talos&tab=detail&external_from=&is_dp_video=0&immersive_square_type=3&video_set_id=${playletId}&play_screen_type=1&play_volume_type=2&play_external_device_type=1`;
const response = await request(`${rule.好看.host}${rule.好看.play}`, {
method: 'POST', headers: aggConfig.headers.haokan, data: { "video/relate": innerParams }
});
try {
const videoData = JSON.parse(response)['video/relate']?.data?.cur_video || {};
const urlMap = {};
if (videoData.clarityUrl) videoData.clarityUrl.forEach(c => { if (c.title && c.url) urlMap[c.title] = c.url; });
if (videoData.video_list) Object.entries(videoData.video_list).forEach(([k, v]) => { if (!urlMap[k]) urlMap[k] = v; });
const sortedQualities = Object.keys(urlMap).sort((a, b) => {
const order = { '4k': 0, '2k': 1, '高清': 2, '蓝光': 3, '超清': 4, '标清': 5 };
return (order[a] ?? 999) - (order[b] ?? 999);
});
const playUrls = [];
sortedQualities.forEach(q => playUrls.push(q, urlMap[q]));
if (playUrls.length > 0) return JSON.stringify({ parse: 0, url: playUrls });
} catch (e) { }
return JSON.stringify({ parse: 0, url: id });
}
if (/百度/.test(flag)) {
const response = await request(`${rule.百度.detailHost}${rule.百度.play}`, {
method: 'POST', headers: aggConfig.headers.baidu, data: { "method": "post", "vid": vid }
});
let json = JSON.parse(response)["video/relate"]?.data?.cur_video;
if (!json?.clarityUrl) return JSON.stringify({ parse: 0, url: id });
let urls = json.clarityUrl.filter(item => item.url && item.title).map(item => ({ title: item.title, url: item.url, order: { '蓝光': 1, '超清': 2, '标清': 3 }[item.title] || 999 })).sort((a, b) => a.order - b.order).flatMap(item => [item.title, item.url]);
return JSON.stringify({ parse: urls.length > 0 ? 0 : 1, url: urls.length > 0 ? urls : id });
}
}
if (/河马/.test(flag)) {
try {
let arr = id.split("++");
let chapterId = arr[0], bookId = arr[2];
let fsbody = JSON.stringify({ "bookId": bookId, "chapterId": chapterId, "unClockType": "pay", "confirmPay": 2, "autoPayFlag": true, "omap": { "channelName": "精选", "logId": "17a6500357709bb2547e1e122b438cfc", "originName": "书城", "recId": "bigdata_rec", "scene": "nsc_727", "sceneId": "dzmf_video_sc_reco", "strategyId": "g6y6b5sq" } });
let fsbodyEnc = hemaEncrypt(fsbody);
let response = await request(rule.河马.host + rule.河马.play, {
method: 'POST', headers: { ...hema_headers, 'Content-Type': 'application/x-www-form-urlencoded' }, data: fsbodyEnc
});
let res = JSON.parse(response);
let fshtml = res.data;
if (fshtml) {
let fsdata = hemaDecrypt(fshtml);
if (fsdata && fsdata !== '{}') {
let parsed = JSON.parse(fsdata);
if (parsed.chaptersPayType == '免费') {
let url = parsed.chapterInfo?.[0]?.content?.m3u8720p || [];
if (url) return JSON.stringify({ parse: 0, url: url });
}
}
}
let playurl = "https://api.cenguigui.cn/api/duanju/hema.php?book_id=" + bookId + "&video_id=" + chapterId + "&type=mp4";
return JSON.stringify({ parse: 0, url: playurl + '#isVideo=true#' });
} catch (e) {
return JSON.stringify({ parse: 0, url: id });
}
}
if (/牛牛/.test(flag)) {
const inputArr = id.split('+');
if (inputArr.length === 2) {
let ep = inputArr[0].match(/\d+/)?.[0] || "";
let videoId = inputArr[1];
let response = await request(`${rule.牛牛.host}/api/v1/app/play/movieDetails`, {
method: 'POST', headers: niuniu_headers, data: { "id": videoId, "source": 0, "typeId": "S1", "userId": "546932", "episodeId": ep }
});
let result = JSON.parse(response);
if (result.code == 200 && result.data?.url) return JSON.stringify({ parse: 0, url: result.data.url });
} else if (inputArr.length === 3) {
let index = inputArr[0], lock_type = inputArr[1], thirdPlayId = inputArr[2];
let data1 = `not_include=0&lock_free=1&type=1&clientVersion=v5.2.5&uuid=6IDYUSASPQY5BBVACWQW3LLTPV4V7DE26UOCX5TZTVUGX4VUJNXQ01&resolution=1080*2320&openudid=82f4175d577a2939&dt=22021211RC&os_api=31&install_id=1496879012031075&sdk_version=1.1.3.0&siteid=5627189&dev_log_aid=667431&oaid=abec0dfff623201b&timestamp=1752498494&direction=0&ac=mobile&os=Android&vod_version=1.10.21.6-tob&os_version=12&count=1&index=1&shortplay_id=${thirdPlayId}&sha1=46121F77CE2FCAD3DBC3B9EC8A24908C1A8AD6D9&device_brand=Redmi&package_name=com.niuniu.ztdh.app`;
if (lock_type === "free") {
let frhtml = await niuniuPost(rule.牛牛.detail2, data1, index);
if (frhtml?.data?.list?.[0]) {
let url = base64Decode(frhtml.data.list[0].video_model.video_list.video_1.main_url);
return JSON.stringify({ parse: 0, url });
}
} else {
let unlockData = `ac=mobile&os=Android&vod_version=1.10.21.6-tob&os_version=12&lock_ad=3&lock_free=3&type=1&clientVersion=v5.2.5&uuid=6IDYUSASPQY5BBVACWQW3LLTPV4V7DE26UOCX5TZTVUGX4VUJNXQ01&resolution=1080*2320&openudid=82f4175d577a2939&shortplay_id=${thirdPlayId}&dt=22021211RC&sha1=46121F77CE2FCAD3DBC3B9EC8A24908C1A8AD6D9&lock_index=21&os_api=31&install_id=1496879012031075&device_brand=Redmi&sdk_version=1.1.3.0&package_name=com.niuniu.ztdh.app&siteid=5627189&dev_log_aid=667431&oaid=abec0dfff623201b&timestamp=1752498493`;
await niuniuPost(rule.牛牛.unlock, unlockData, index);
let unhtml = await niuniuPost(rule.牛牛.detail2, data1, index);
if (unhtml?.data?.list?.[0]) {
let url = base64Decode(unhtml.data.list[0].video_model.video_list.video_1.main_url);
return JSON.stringify({ parse: 0, url });
}
}
}
return JSON.stringify({ parse: 0, url: id });
}
if (/围观/.test(flag)) {
try {
let playSetting = typeof id === 'string' ? JSON.parse(id) : id;
let urls = [];
if (playSetting.super) urls.push("超清", playSetting.super);
if (playSetting.high) urls.push("高清", playSetting.high);
if (playSetting.normal) urls.push("流畅", playSetting.normal);
return JSON.stringify({ parse: 0, url: urls.length ? urls : id });
} catch (e) {
return JSON.stringify({ parse: 0, url: id });
}
}
return JSON.stringify({ parse: 0, url: id });
}
// ==================== 工具函数 ====================
function buildUrlQuery(params) {
return Object.keys(params).map(k => `${encodeURIComponent(k)}=${encodeURIComponent(params[k])}`).join('&');
}
async function md5(str) {
return CryptoJS.MD5(str).toString(CryptoJS.enc.Hex).toLowerCase();
}
function base64Encode(text) {
return CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(text));
}
function base64Decode(text) {
return CryptoJS.enc.Utf8.stringify(CryptoJS.enc.Base64.parse(text));
}
function hmacSHA256(data, key) {
return CryptoJS.HmacSHA256(data, key).toString(CryptoJS.enc.Hex);
}
function aesEncryptECB(text, keyStr) {
let key = CryptoJS.enc.Utf8.parse(keyStr);
return CryptoJS.AES.encrypt(text, key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 }).toString();
}
function aesDecryptECB(ciphertext, keyStr) {
let key = CryptoJS.enc.Utf8.parse(keyStr);
return CryptoJS.AES.decrypt(ciphertext, key, { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 }).toString(CryptoJS.enc.Utf8);
}
function hemaEncrypt(plaintext) {
let key = CryptoJS.enc.Hex.parse("647a6b6a67667978677368796c677a6d");
let iv = CryptoJS.enc.Hex.parse("6170697570646f776e65646372797074");
let encrypted = CryptoJS.AES.encrypt(plaintext, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 });
return encrypted.ciphertext.toString(CryptoJS.enc.Hex).toUpperCase();
}
function hemaDecrypt(word) {
let key = CryptoJS.enc.Hex.parse("647a6b6a67667978677368796c677a6d");
let iv = CryptoJS.enc.Hex.parse("6170697570646f776e65646372797074");
let srcs = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Hex.parse(word));
let decrypt = CryptoJS.AES.decrypt(srcs, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 });
return decrypt.toString(CryptoJS.enc.Utf8);
}
async function niuniuPost(url1, data1, index) {
let t10 = String(Math.floor(Date.now() / 1000));
let X_Nonce = "X9UknYKtLa3DmtjC";
let body1 = data1.replace(/&lock_free=\d+/, "&lock_free=1").replace(/&timestamp=\d+/, "&timestamp=" + t10).replace(/&count=\d+/, "&count=1").replace(/&index=\d+/, "&index=" + index).replace(/&lock_ad=\d+/, "&lock_ad=1").replace(/&lock_index=\d+/, "&lock_index=" + index);
let body2 = aesEncryptECB(body1, 'ce49b18dd4e0a4d8');
let signature = hmacSHA256(t10 + X_Nonce + body1, 'aceaa47f96b4875d446b2e1d97e03bbb');
let res = await request(url1, {
method: 'POST',
headers: { 'X-Salt': 'FD8188A8D5', 'X-Nonce': X_Nonce, 'X-Timestamp': t10, 'X-Access-Token': niuniu_access_token, 'X-Signature': signature, 'Content-Type': 'application/x-www-form-urlencoded', 'User-Agent': 'okhttp/4.12.0' },
data: body2
});
if (!res) return {};
try { return JSON.parse(aesDecryptECB(res, 'ce49b18dd4e0a4d8')); } catch (e) { return {}; }
}
async function request(url, options = {}) {
let reqHeaders = { ...aggConfig.headers.form, ...options.headers };
let finalUrl = url;
let requestData = options.data;
let useBody = false;
// POST + 字符串 + form类型 → 直接作为body发送(保留空格,牛牛接口需要)
if (options.method === 'POST' && typeof options.data === 'string' && reqHeaders['Content-Type']?.includes('form')) {
useBody = true;
}
// GET请求处理
if ((options.method === 'GET' || !options.method) && options.data && !useBody) {
let queryData = options.data;
if (typeof queryData === 'string') {
try { queryData = JSON.parse(queryData); } catch (e) { queryData = {}; }
}
finalUrl = url + (url.includes('?') ? '&' : '?') + buildUrlQuery(queryData);
requestData = null;
}
// 确定postType(关键!告诉req如何处理data)
let postType = '';
if (!useBody && options.data) {
let ct = reqHeaders['Content-Type'] || '';
postType = ct.includes('json') ? 'json' : (ct.includes('form') ? 'form' : '');
}
try {
const res = await req(finalUrl, {
method: options.method || 'GET',
headers: reqHeaders,
...(useBody ? { body: requestData } : { data: requestData, postType: postType }),
timeout: options.timeout || 15000
});
return res?.content || res?.data || res;
} catch (e) {
log(2, '请求', e.message);
return null;
}
}
// ==================== 导出 ====================
export function __jsEvalReturn() {
return { init, home, homeVod, category, detail, play, search };
}
+589
View File
@@ -0,0 +1,589 @@
/**
* title: "喵物次元",
* logo: "https://www.mwcy.net/favicon.ico",
* more: {
* sourceTag: "动漫"
* }
*/
import { Crypto, load, _ } from 'assets://js/lib/cat.js';
const HOST = 'https://www.mwcy.net';
const UA = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36';
let siteKey = "", siteType = "", sourceKey = "", ext = "";
function init(cfg) {
siteKey = cfg.skey;
siteType = cfg.stype;
sourceKey = cfg.sourceKey;
ext = cfg.ext;
// 如果ext传入则覆盖HOST(保持兼容)
if (ext && ext.indexOf('http') == 0) HOST = ext;
}
// ==================== 辅助函数 ====================
function fixUrl(url) {
if (!url) return '';
url = url.trim();
if (url.startsWith('//')) return 'https:' + url;
if (url.startsWith('/')) return HOST + url;
return url;
}
function cleanText(text) {
if (!text) return '';
return text.replace(/\s+/g, ' ').trim();
}
function isVideoFormat(url) {
if (!url) return false;
return /\.(m3u8|mp4|mkv|flv|avi|mov|wmv|webm)(\?.*)?$/i.test(url);
}
// ==================== 1. 首页内容与筛选配置 ====================
function home(filter) {
// 固定分类(6个)
const classes = [
{ type_id: "1", type_name: "番剧" },
{ type_id: "22", type_name: "连载新番" },
{ type_id: "24", type_name: "国漫" },
{ type_id: "2", type_name: "剧场" },
{ type_id: "25", type_name: "欧美动漫" },
{ type_id: "26", type_name: "4K专区" }
];
// ---- 公共筛选选项 ----
// 年份:当前年份往前30年 + 更早
const yearList = (() => {
const years = [{ n: "全部", v: "" }];
const currentYear = new Date().getFullYear();
for (let y = currentYear; y >= currentYear - 30; y--) {
years.push({ n: String(y), v: String(y) });
}
years.push({ n: "更早", v: "更早" });
return years;
})();
// 字母
const letterList = (() => {
const letters = [{ n: "全部", v: "" }];
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
chars.forEach(c => letters.push({ n: c, v: c }));
letters.push({ n: "0-9", v: "0-9" });
return letters;
})();
// 排序
const orderList = [
{ n: "最新", v: "time" },
{ n: "最热", v: "hits" },
{ n: "评分", v: "score" }
];
// 地区(用于剧场、欧美动漫)
const areaList = [
{ n: "全部", v: "" },
{ n: "大陆", v: "大陆" },
{ n: "香港", v: "香港" },
{ n: "台湾", v: "台湾" },
{ n: "美国", v: "美国" },
{ n: "法国", v: "法国" },
{ n: "英国", v: "英国" },
{ n: "日本", v: "日本" },
{ n: "韩国", v: "韩国" },
{ n: "德国", v: "德国" },
{ n: "泰国", v: "泰国" },
{ n: "印度", v: "印度" },
{ n: "意大利", v: "意大利" },
{ n: "西班牙", v: "西班牙" },
{ n: "加拿大", v: "加拿大" },
{ n: "其他", v: "其他" }
];
// ---- 按分类配置筛选器 ----
const filters = {
"1": [ // 番剧
{ key: "year", name: "年份", value: yearList },
{ key: "letter", name: "字母", value: letterList },
{ key: "order", name: "排序", value: orderList }
],
"22": [ // 连载新番
{ key: "year", name: "年份", value: yearList },
{ key: "letter", name: "字母", value: letterList },
{ key: "order", name: "排序", value: orderList }
],
"24": [ // 国漫
{ key: "year", name: "年份", value: yearList },
{ key: "letter", name: "字母", value: letterList },
{ key: "order", name: "排序", value: orderList }
],
"2": [ // 剧场
{ key: "area", name: "地区", value: areaList },
{ key: "year", name: "年份", value: yearList },
{ key: "letter", name: "字母", value: letterList },
{ key: "order", name: "排序", value: orderList }
],
"25": [ // 欧美动漫
{ key: "area", name: "地区", value: areaList },
{ key: "year", name: "年份", value: yearList },
{ key: "letter", name: "字母", value: letterList },
{ key: "order", name: "排序", value: orderList }
],
"26": [ // 4K专区
{ key: "letter", name: "字母", value: letterList },
{ key: "order", name: "排序", value: orderList }
]
};
return JSON.stringify({ class: classes, filters: filters });
}
// ==================== 2. 首页推荐视频 ====================
async function homeVod() {
try {
const res = await req(HOST, { headers: { 'User-Agent': UA } });
const $ = load(res.content);
// 定位“十月新番”区域
let section = null;
$('.box-width.wow.fadeInUp .title .title-h').each((i, el) => {
if ($(el).text().trim() === '十月新番') {
section = $(el).closest('.box-width').find('.public-r');
return false;
}
});
if (!section) {
section = $('.public-list-box.public-pic-b').parent();
}
const items = section ? section.find('.public-list-box.public-pic-b') : $('.public-list-box.public-pic-b');
const videos = [];
const seen = new Set();
items.each((i, el) => {
const $el = $(el);
const $link = $el.find('a.public-list-exp');
const href = $link.attr('href');
if (!href || !href.startsWith('/bangumi/')) return;
const title = $el.find('.time-title').text().trim() || $link.attr('title') || '';
const pic = $link.find('img').attr('data-src') || $link.find('img').attr('src') || '';
const remarks = $el.find('.public-list-prb').text().trim() || '';
if (title && href) {
const vod_id = href.startsWith('http') ? href : HOST + href;
if (!seen.has(vod_id)) {
seen.add(vod_id);
videos.push({ vod_id, vod_name: title, vod_pic: pic, vod_remarks: remarks });
}
}
});
return JSON.stringify({ list: videos });
} catch (e) {
console.log('homeVod error:', e);
return null;
}
}
// ==================== 3. 分类内容爬取 ====================
async function category(tid, pg, filter, extend) {
if (pg <= 0) pg = 1;
extend = extend || {};
const area = extend.area || '';
const year = extend.year || '';
const letter = extend.letter || '';
const order = extend.order || '';
// 构建URL
let url = `${HOST}/show/${tid}`;
const parts = [];
if (area) parts.push(`area/${encodeURIComponent(area)}`);
if (order) parts.push(`by/${encodeURIComponent(order)}`);
if (letter) parts.push(`letter/${encodeURIComponent(letter)}`);
if (year) parts.push(`year/${encodeURIComponent(year)}`);
if (pg > 1) parts.push(`page/${pg}`);
if (parts.length > 0) {
url += '/' + parts.join('/') + '.html';
} else {
url += (pg === 1 ? '.html' : `/page/${pg}.html`);
}
try {
const res = await req(url, { headers: { 'User-Agent': UA } });
const $ = load(res.content);
// 解析视频列表(多级兜底)
let items = $('.public-list-box.public-pic-b');
if (!items.length) items = $('.public-list-div').parent();
const videos = [];
const seen = new Set();
items.each((i, el) => {
const $el = $(el);
const $link = $el.find('a.public-list-exp');
const href = $link.attr('href');
if (!href) return;
let vod_id = href;
if (!href.startsWith('http')) vod_id = HOST + href;
// 如果是 /play/ 链接,转换为 /bangumi/
if (href.startsWith('/play/')) {
const match = href.match(/^\/play\/([^-]+)/);
if (match) {
vod_id = HOST + `/bangumi/${match[1]}.html`;
} else {
return;
}
} else if (!href.startsWith('/bangumi/')) {
return;
}
const title = $el.find('.time-title').text().trim() || $link.attr('title') || '';
const pic = $link.find('img').attr('data-src') || $link.find('img').attr('src') || '';
const remarks = $el.find('.public-list-prb').text().trim() || '';
if (title && vod_id && !seen.has(vod_id)) {
seen.add(vod_id);
videos.push({
vod_id,
vod_name: title,
vod_pic: fixUrl(pic),
vod_remarks: remarks
});
}
});
// 提取总页数
let pagecount = 1;
const pageTip = $('.page-tip').text().trim();
if (pageTip) {
const match = pageTip.match(/当前\d+\/(\d+)页/);
if (match) pagecount = parseInt(match[2]) || 1;
}
if (pagecount === 1) {
const lastPage = $('.page-link').last().attr('href');
if (lastPage) {
const m = lastPage.match(/page\/(\d+)\.html/);
if (m) pagecount = parseInt(m[1]) || 1;
}
}
return JSON.stringify({
list: videos,
page: pg,
pagecount: pagecount,
limit: 20,
total: videos.length
});
} catch (e) {
console.log('category error:', e);
return JSON.stringify({ list: [] });
}
}
// ==================== 4. 搜索功能 ====================
async function search(wd) {
try {
const encoded = encodeURIComponent(wd);
const url = `${HOST}/search/wd/${encoded}.html`;
const res = await req(url, { headers: { 'User-Agent': UA } });
const $ = load(res.content);
// 搜索页结果使用 .vod-detail.search-list
let items = $('.vod-detail.search-list');
if (!items.length) items = $('.vod-detail');
const videos = [];
const seen = new Set();
items.each((i, el) => {
const $el = $(el);
// 标题和链接
let title = '';
let vod_id = '';
const titleEl = $el.find('h3.slide-info-title');
if (titleEl.length) title = titleEl.text().trim();
const linkEl = $el.find('a[target="_blank"]');
if (linkEl.length) {
const href = linkEl.attr('href');
if (href) {
if (href.startsWith('/bangumi/')) {
vod_id = HOST + href;
} else if (href.startsWith('/play/')) {
const match = href.match(/^\/play\/([^-]+)/);
if (match) vod_id = HOST + `/bangumi/${match[1]}.html`;
}
}
if (!title) title = linkEl.text().trim();
}
if (!title) {
// 从其他位置找
const altTitle = $el.find('.slide-info-title').text().trim();
if (altTitle) title = altTitle;
}
const pic = $el.find('.detail-pic img').attr('data-src') || $el.find('.detail-pic img').attr('src') || '';
const remarks = $el.find('.slide-info-remarks').first().text().trim() || '';
if (title && vod_id && !seen.has(vod_id)) {
seen.add(vod_id);
videos.push({
vod_id,
vod_name: title,
vod_pic: fixUrl(pic),
vod_remarks: remarks
});
}
});
// 总页数
let pagecount = 1;
const pageTip = $('.page-tip').text().trim();
if (pageTip) {
const match = pageTip.match(/当前\d+\/(\d+)页/);
if (match) pagecount = parseInt(match[2]) || 1;
}
return JSON.stringify({
list: videos,
page: 1,
pagecount: pagecount,
limit: 20,
total: videos.length
});
} catch (e) {
console.log('search error:', e);
return JSON.stringify({ list: [] });
}
}
// ==================== 5. 详情页解析 ====================
async function detail(id) {
try {
const url = id.startsWith('http') ? id : HOST + id;
const res = await req(url, { headers: { 'User-Agent': UA } });
const $ = load(res.content);
// 标题
let vod_name = $('h3.slide-info-title').text().trim();
if (!vod_name) vod_name = $('.player-title-link').text().trim();
if (!vod_name) vod_name = $('title').text().replace(/^.*? - /, '').replace(/ - .*$/, '');
// 封面
let vod_pic = $('.detail-pic img').attr('data-src') || $('.detail-pic img').attr('src') || '';
if (!vod_pic) vod_pic = $('.vod-detail .detail-pic img').attr('data-src') || '';
// 简介
let vod_content = $('#height_limit').text().trim() || $('.vod-news .text').first().text().trim() || '';
// 元数据:年份、地区、类型
let vod_year = '', vod_area = '';
$('.slide-info .slide-info-remarks a').each((i, el) => {
const text = $(el).text().trim();
if (/^\d{4}$/.test(text)) vod_year = text;
else if (['日本','大陆','香港','台湾','美国','英国','韩国','法国','德国','泰国','印度','意大利','西班牙','加拿大','其他'].includes(text)) {
vod_area = text;
}
});
// 类型
// ---- 提取演员和导演 ----
let vod_actor = '', vod_director = '', type_name = '';
// 方式1:从 .slide-info.partition 中提取
$('.slide-info.partition').each((i, el) => {
const $el = $(el);
// 类型
const typeStrong = $el.find('strong:contains("类型")');
if (typeStrong.length) {
const typeLinks = typeStrong.nextAll('a').map((j, a) => $(a).text().trim()).get();
if (typeLinks.length) type_name = typeLinks.join(',');
}
// 导演
const dirStrong = $el.find('strong:contains("导演")');
if (dirStrong.length) {
const dirLinks = dirStrong.nextAll('a').map((j, a) => $(a).text().trim()).get();
if (dirLinks.length) vod_director = dirLinks.join(',');
}
// 演员
const actorStrong = $el.find('strong:contains("演员")');
if (actorStrong.length) {
const actorLinks = actorStrong.nextAll('a').map((j, a) => $(a).text().trim()).get();
if (actorLinks.length) vod_actor = actorLinks.join(',');
}
});
// ---- 播放源与剧集 ----
const playFrom = [];
const playUrls = [];
// 获取线路名称
const sourceNames = [];
$('.anthology-tab a').each((i, el) => {
let name = $(el).text().trim();
name = name.replace(/<i[^>]*>.*?<\/i>/, '').replace(/&nbsp;/g, '').replace(/<span[^>]*>.*?<\/span>/, '').trim();
if (name) sourceNames.push(name);
});
if (!sourceNames.length) {
$('.vod-playerUrl').each((i, el) => {
let name = $(el).text().trim();
name = name.replace(/<i[^>]*>.*?<\/i>/, '').replace(/<span[^>]*>.*?<\/span>/, '').trim();
if (name) sourceNames.push(name);
});
}
const boxes = $('.anthology-list-box');
if (boxes.length && sourceNames.length) {
boxes.each((idx, box) => {
const name = sourceNames[idx] || ('线路' + (idx+1));
const episodes = [];
$(box).find('ul.anthology-list-play li a').each((j, ep) => {
const $ep = $(ep);
let epName = $ep.find('span').text().trim() || $ep.text().trim();
let href = $ep.attr('href');
if (epName && href) {
href = fixUrl(href);
episodes.push(epName + '$' + href);
}
});
if (episodes.length) {
playFrom.push(name);
playUrls.push(episodes.join('#'));
}
});
}
if (!playFrom.length) {
const singleBox = $('.anthology-list-play');
if (singleBox.length) {
const episodes = [];
singleBox.find('li a').each((j, ep) => {
const $ep = $(ep);
let epName = $ep.find('span').text().trim() || $ep.text().trim();
let href = $ep.attr('href');
if (epName && href) {
href = fixUrl(href);
episodes.push(epName + '$' + href);
}
});
if (episodes.length) {
playFrom.push('默认线路');
playUrls.push(episodes.join('#'));
}
}
}
const vod = {
vod_id: id,
vod_name,
vod_pic: fixUrl(vod_pic),
type_name,
vod_actor: vod_actor,
vod_director: vod_director,
vod_year,
vod_area,
vod_remarks: '',
vod_content,
vod_play_from: playFrom.join('$$$'),
vod_play_url: playUrls.join('$$$')
};
return JSON.stringify({ list: [vod] });
} catch (e) {
console.log('detail error:', e);
return null;
}
}
// ==================== 6. 播放链接解析 ====================
async function play(flag, id, flags) {
try {
const playUrl = id.startsWith('http') ? id : HOST + id;
const res = await req(playUrl, { headers: { 'User-Agent': UA } });
const html = res.content;
const match = html.match(/player_.*?=([^]*?)</);
if (!match) return JSON.stringify({ parse: 1, url: playUrl });
const config = JSON.parse(match[1]);
let videoUrl = (config.url || '').trim();
if (!videoUrl) return JSON.stringify({ parse: 1, url: playUrl });
const directVideoPattern = /\.(m3u8|mp4|mkv|flv|avi|mov|wmv|webm)(\?.*)?$/i;
if (directVideoPattern.test(videoUrl)) {
console.log('videoUrl:', videoUrl);
return JSON.stringify({ parse: 0, url: videoUrl });
}
const tryParse = async (apiPath) => {
try {
const apiUrl = `https://player.catw.moe${apiPath}${encodeURIComponent(videoUrl)}&_t=${Date.now()}`;
const res = await req(apiUrl, { headers: { 'User-Agent': UA } });
const html = res.content;
// 提取 uid
const uidMatch = html.match(/"uid"\s*:\s*"([^"]+)"/);
const uid = uidMatch ? uidMatch[1] : null;
console.log('uid:', uid);
// 提取 url (ConFig 根层级那个长字符串)
const urlMatch = html.match(/"url"\s*:\s*"([^"]+)"/);
const url = urlMatch ? urlMatch[1] : null;
console.log('url:', url);
if (!uid || !url) {
console.log('[喵物次元] ConFig 缺少 uid 或 url');
return null;
}
const realUrl = decryptEcUrl(url, uid);
if (realUrl) {
return { url: realUrl, ua: UA };
}
return null;
} catch (e) {
return null;
}
};
let parsed = await tryParse('/player/ec.php?code=qw&if=1&url=');
if (!parsed) parsed = await tryParse('/art.php?url=');
if (parsed) {
return JSON.stringify({
parse: 0,
url: parsed.url,
header: { 'User-Agent': parsed.ua }
});
}
return JSON.stringify({ parse: 1, url: playUrl });
} catch (e) {
return JSON.stringify({ parse: 1, url: id });
}
}
function decryptEcUrl(encryptedBase64, uid) {
try {
const aesKey = '2890' + uid + 'tB959C';
const aesIv = '2F131BE91247866E';
// aesX(算法, 加密?false=解密, 数据, 输入是Base64?, key, iv, 输出是Base64?)
const realUrl = aesX('AES/CBC/PKCS7', false, encryptedBase64, true, aesKey, aesIv, false);
console.log(realUrl)
return realUrl;
} catch (e) {
return null;
}
}
// ==================== 导出 ====================
export function __jsEvalReturn() {
return {
init,
home,
homeVod,
category,
detail,
play,
search
};
}
+19
View File
@@ -0,0 +1,19 @@
{
"作者":"20260317",
"站名":"4K在线-永久发布页https://4kfabuye.top/",
"主页url": "https://bbibi.cc/",
"请求头": "User-Agent$MOBILE_UA",
"简介":"description\" content=\"&&\"",
"线路二次截取": "播放地址&&</ul>",
"线路数组": "<a&&/a>",
"线路标题": ">&&<",
"播放数组": "text-muted col-pd\">&&</ul",
"播放列表": "<li&&</li",
"播放标题": "title=\"&&\"",
"播放链接": "href=\"&&\"",
"搜索url":"https://bbibi.cc/search.php?page={catePg}&searchword={wd}",
"搜索模式":"1",
"分类url":"https://www.bbibi.cc/search.php?page={catePg}&searchtype=5&order={by}&tid={cateId}&area={area}&year={year}&letter={letter};;",
"分类": "电影$1#电视剧$2#综艺$3#动漫$4"
}
@@ -0,0 +1,41 @@
{
"作者": "20260402",
"站名": "4K影视4kvm.site",
"请求头": "User-Agent$MOBILE_UA",
"编码": "UTF-8",
"图片代理": "0",
"备用地址": "https://4kvm.site/",
"免嗅": "1",
"嗅探词": ".mp4#.m3u8#.flv#https://lf16-fe.resso.me",
"主页url": "https://www.4kvm.org/",
"首页": "120",
"起始页": "1",
"分类url": "https://www.4kvm.org/filter?classify={cateId}&page={catePg};;rc",
"分类": "电影&剧集&动漫",
"分类值": "1&2&3",
"数组": "data-vod-id=&&</a>",
"标题": "alt=\"&&\"",
"图片": "https://+src=\"https*src=&&\"",
"副标题": "update\">&&</div>+icon-star2\">&&</div>",
"链接前缀": "https://www.4kvm.org",
"链接": "href=\"&&\"",
"导演": "导演</div>*>&&</div>",
"主演": "主演</div>*>&&</div>",
"简介": "👉【提醒:请不要相信视频中的广告以免上当受骗!】,+description\" content=\"&&\"",
"线路数组": "se-q'>&&</a>",
"线路标题": "专线",
"多线数组": "se-q'>&&</a>",
"多线链接": "href=\"&&\"",
"搜索url": "https://www.4kvm.org/search?q={wd}",
"搜索模式": "1",
"搜索数组": "<a &&</a>[包含:/play/]",
"搜索标题": "alt=\"&&\"",
"搜索图片": "https://+src=\"https*src=&&\"",
"搜索链接前缀": "https://www.4kvm.org",
"搜索链接": "href=\"&&\"",
"倒序": "0",
"播放列表": "<a &&</a>[包含:/play/]",
"播放标题": "<span x-show=\"!isEpisodeActive*>&&</span",
"播放链接": "href=\"&&\"",
"播放链接前缀": "https://www.4kvm.org"
}
+12
View File
@@ -0,0 +1,12 @@
{
"站名": "4K舱影视",
"请求头": "手机",
"主页url":"https://www.4kcabin.com/",
"数组": "myui-vodbox-content\">&&</a>",
"图片": "src=\"&&\"",
"标题":"class=\"title\">&&</",
"链接":"href=\"&&\"",
"搜索":"https://www.4kcabin.com/vodsearch/-------------.html?wd={wd}",
"分类":"电影$dianying#连续剧$dianshiju#综艺$zongyi#动漫$dongman#短剧$duanju",
"分类url": "https://www.4kcabin.com/vodshow/{cateId}-{area}--{class}-----{catePg}---{year}.html"
}
+80
View File
@@ -0,0 +1,80 @@
{
"作者": "菜妮丝,修复首页与分页不同",
"站名": "Auete影视地址发布页https://v.auete.com/",
"主页url": "https://www.au1080.com/",
"分类": "电影$Movie#电视剧$Tv#综艺$Zy#动漫$Dm#其他$qita",
//"分类url": "https://auete.top/{cateId}{class}/index{catePg}.html[https://auete.com/{cateId}/index.html]",
"分类url": "https://www.au1080.com/{cateId}{class}/index{catePg}.html",
"起始页": "2",
"数组": "<li class=\"trans_3&&/button>",
"副标题": "hdtag\">&&<",
"搜索模式": "1",
"搜索url": "/aueteso.php?searchword={wd}",
"搜索数组": "mb-0\">&&</a>",
"搜索图片": "空",
"搜索标题": "text-danger\">&&<",
"搜索链接": "data-href=\"&&\"",
"影片地区": "地区:&&</p>",
"影片类型": "分类:&&</p>",
"导演": "导演:&&</p>",
"主演": "主演:&&</p>",
"简介": "</a><p>&&</p>",
"线路数组": "<i class=\"icon-film\">&&small>",
"线路标题": ">&&<[替换:『*』>>空#>>空]",
"播放数组": "</h2><ul>&&</ul>",
"筛选":{
"Movie":[
{"key":"class","name":"剧情","value":[
{"n":"全部","v":""},
{"n":"喜剧片","v":"/xjp"},
{"n":"动作片","v":"/dzp"},
{"n":"爱情片","v":"/aqp"},
{"n":"科幻片","v":"/khp"},
{"n":"恐怖片","v":"/kbp"},
{"n":"惊悚片","v":"/jsp"},
{"n":"战争片","v":"/zzp"},
{"n":"剧情片","v":"/jqp"}]}],
"Tv":[
{"key":"class","name":"剧情","value":[
{"n":"全部","v":""},
{"n":"美剧","v":"/oumei"},
{"n":"韩剧","v":"/hanju"},
{"n":"日剧","v":"/riju"},
{"n":"泰剧","v":"/yataiju"},
{"n":"网剧","v":"/wangju"},
{"n":"台剧","v":"/taiju"},
{"n":"国产","v":"/neidi"},
{"n":"港剧","v":"/tvbgj"},
{"n":"英剧","v":"/yingju"}]}],
"Zy":[
{"key":"class","name":"剧情","value":[
{"n":"全部","v":""},
{"n":"国综","v":"/guozong"},
{"n":"韩综","v":"/hanzong"},
{"n":"美综","v":"/meizong"}]}],
"Dm":[
{"key":"class","name":"剧情","value":[
{"n":"全部","v":""},
{"n":"动画","v":"/donghua"},
{"n":"日漫","v":"/riman"},
{"n":"国漫","v":"/guoman"},
{"n":"美漫","v":"/meiman"}]}],
"qita":[
{"key":"class","name":"剧情","value":[
{"n":"全部","v":""},
{"n":"记录片","v":"/Jlp"},
{"n":"经典片","v":"/Jdp"},
{"n":"经典剧","v":"/Jdj"},
{"n":"网大电影","v":"/wlp"},
{"n":"国产老电影","v":"/laodianying"}]}]}
}
+34
View File
@@ -0,0 +1,34 @@
{
"站名": "🎈️CNN影视🎈",
"播放请求头": "User-Agent$Mozilla/5.0",
"二次截取": "videoList*[&&]",
"数组": "{&&}",
"图片": "https://obs.3688baihuo.com/+huo.com/&&\"",
"标题": "\"vodName\":\"&&\"",
"副标题": "vodRemarks\":\"(&&\"",
"链接": "\"vodId\":&&,",
"链接前缀": "https://m.shunhengdf.com/detail/",
"简介": "简介:&&\"",
"搜索url": "https://m.shunhengdf.com/vod/search/{wd}",
"搜索副标题": "class=\"boottom\"*<div>&&</div",
"线路数组": "<div class=\"player_name&&div>",
"线路标题": ">&&</",
"播放数组":"episodeList\":\\[&&\\][替换:nid\":>>nid\":/1/]",
"播放列表":"{&&}",
"播放标题":"name\":\"&&\"",
"播放链接前缀":"https://m.shunhengdf.com/vod/play/+data\":{\"vodId\":&&,",
"播放链接":"nid\":&&,",
"倒序":"0",
"跳转解析":"",
"跳转播放链接":"",
"分类url":"https://m.shunhengdf.com/vod/show/id/{cateId}/class/{class}/area/{area}/year/{year}/page/{catePg}",
"分类":"电影$1#电视剧$2#综艺$3#动漫$4"
}
@@ -0,0 +1,138 @@
//写法思路来海阔视界,xpath筛选。本人是海阔用户,所以搬了海阔的jsoup写法过来。2022年9月17日
//jsoup规则写法请查阅海阔视界或者海阔影视相关教程。不支持js写法
//本文档为完整模板,请不要去无中生有添加多余的键值参数。
{
//规则名
"title": "Vidhub视频库",
//作者
"author": "香雅情",
//请求头UA,键名$键值,每一组用#分开,不填则默认okhttp/3.12.11,可填MOBILE_UA或PC_UA使用内置的手机版或电脑版UA
//多个请求头参数写法示例,"User-Agent$PC_UA#Referer$http://ww.baidu.com#Cookie$ser=ok",每一组用#分开。
//习惯查看手机源码写建议用手机版UA,习惯查看PC版源码写建议用电脑版UA
"Headers":"PC_UA",
//图片是否需要代理
"PicNeedProxy":"0",
//是否开启获取首页数据,0关闭,1开启
"homeContent":"1",
//首页推荐数据获取链接
"rcmed_url": "https://vidhub.tv",
//首页列表数组截取。
"home_arr_rule": "body&&.module-items",
//首页片单列表数组定位。
"hmepi_arr_rule": ".module-item:not(:contains(伦理片))",
//首页片单信息jsoup与正则截取写法切换,只作用于html网页,1为jsoup写法(默认),0为正则截取写法
"home_is_jsoup":"1",
//分类链接起始页码,禁止负数和含小数点。
"firstpage": "1",
//分类链接,{cateId}是分类,{catePg}是页码,第一页没有页码的可以这样写 第二页链接[firstPage=第一页的链接]
"class_url": "https://vidhub.tv/vodshow/{cateId}--hits------{catePg}---.html[firstPage=https://vidhub.tv/vodshow/{cateId}--hits---------.html]",
//分类名,分类1&分类2&分类3
"class_name": "电影&电视剧&动漫&综艺",
//分类名替换词,替换词1&替换词2&替换词3,替换词包含英文&的用两个中文&&代替,示例:&&id=0&&&id=1
"class_value": "1&2&4&3",
//筛选数据,json格式,参考xpath的筛选写法
"filterdata":{},
//分类页面截取数据模式,0为json,其它数字为普通网页。
"cat_mode": "1",
//分类列表数组定位,最多支持3层,能力有限,不是所有页面都能支持
"cat_arr_rule": ".module-items&&.module-item:not(:contains(伦理片))",
//分类片单信息jsoup与xb截取写法切换,只作用于html网页,1为jsoup写法(默认)0为xb写法
"cat_is_jsoup":"1",
//分类片单标题
"cat_title": "a&&title",
//分类片单链接
"cat_url": "a&&href",
//分类片单图片,支持自定义图片链接
"cat_pic": ".lazyloaded&&data-src",
//分类片单副标题
"cat_subtitle":".module-item-text&&Text",
//分类片单链接补前缀
"cat_prefix": "https://vidhub.tv",
//分类片单链接补后缀
"cat_suffix": "",
//搜索请求头参数,不填则默认okhttp/3.12.11,可填MOBILE_UA或PC_UA使用内置的手机版或电脑版UA
//多个请求头参数写法示例,键名$键值,每一组用#分开。"User-Agent$PC_UA#Referer$http://ww.baidu.com#Cookie$ser=ok"。
"SHeaders":"User-Agent$PC_UA",
//搜索链接,搜索关键字用{wd}表示,post请求的最后面加;post
//POST链接示例 http://www.lezhutv.com/index.php?m=vod-search;post
"search_url": "https://vidhub.tv/index.php/ajax/suggest?mid=1&wd={wd}&limit=50",
//POST搜索body,填写搜索关键字的键值,一般常见的是searchword和wd,不是POST搜索的可留空或删除。
"sea_PtBody":"wd={wd}&search=",
//搜索截取模式,0为json搜索,只支持列表在list数组里的,其它数字为网页截取。
"search_mode": "0",
//搜索列表数组定位,不填默认内置list,最多支持3层,能力有限,不是所有页面都能支持。
"sea_arr_rule": "list",
//搜索片单信息jsoup与xb截取写法切换,只作用于html网页,1为jsoup写法(默认)0为xb写法
"sea_is_jsoup":"1",
//搜索片单图片,支持自定义图片链接
"sea_pic": "pic",
//搜索片单标题
"sea_title": "name",
//搜索片单链接
"sea_url": "id",
//搜索片单副标题
"sea_subtitle":"",
//搜索片单链接补前缀
"search_prefix": "https://vidhub.tv/voddetail/",
//搜索片单链接补后缀,这个一般json搜索的需要
"search_suffix": ".html",
//片单链接是否直接播放,0否,1分类片单链接直接播放,2详情选集链接直接播放。
//设置成直接播放后,后面3个参数请注意该留空的请务必留空。
"force_play": "0",
//直接播放链接补前缀
"play_prefix": "https://live.52sf.ga/huya/",
//直接播放链接补后缀,设置为#isVideo=true#可强制识别为视频链接
"play_suffix": "#isVideo=true#",
//直接播放链接设置请求头,只对直链视频有效,每一组用#分开
"play_header": "authority$ku.peizq.online#Referer$https://play.peizq.online",
//项目信息jsoup与xb截取写法切换,1为jsoup写法(默认),0为xb写法
"proj_is_jsoup":"1",
//类型数据,截取前缀&&截取后缀
"proj_cate": ".video-info&&.video-info-aux&&Text",
//年代数据,截取前缀&&截取后缀
"proj_year": ".video-info&&.video-info-items,2&&Text",
//地区数据,截取前缀&&截取后缀
"proj_area": "",
//演员数据,截取前缀&&截取后缀
"proj_actor": ".video-info&&.video-info-items,1&&Text",
//简介内容,截取前缀&&截取后缀
"proj_plot": ".video-info&&.video-info-content&&Text",
//线路截取区域,如果不需要请把tab_title或tab_arr_rule置空或者全部不要填。
//线路截取数组
"tab_arr_rule": ".module-tab-items&&.module-tab-item",
//线路标题,截取前缀&&截取后缀
"tab_title": "Text",
//列表数组截取,必须
"list_arr_rule": "body&&.module-player-list",
//集数数组截取,必须
"epi_arr_rule": ".scroll-content&&a",
//集数标题,截取前缀&&截取后缀
"epi_title": "Text",
//集数链接,截取前缀&&截取后缀
"epi_url": "href",
//选集是否反转显示
"epi_reverse": "0",
//集数链接补前缀
"epiurl_prefix": "https://vidhub.tv",
//集数链接补后缀
"epiurl_suffix": "",
//下面几个参数请勿乱用。否则可能会有副作用。
//分析网页源码中有<script type="text/javascript">var player_aaaa={"flag":"play","encrypt这种源码的链接解析
//如果网页源码里没有这种请设置为0
"Anal_MacPlayer":"0",
//是否开启手动嗅探,只对网页嗅探有效,0否,1是
"ManualSniffer":"1",
//手动嗅探视频链接关键字,每个用#隔开
"VideoFormat":".mp4#.m3u8#.flv#player/m3u8",
//手动嗅探视频链接过滤关键词,每个用#隔开
"VideoFilter":".html#=http"
}
+33 -46
View File
@@ -1,46 +1,33 @@
{
"站名":"厂长影视",
"主页url":"https://czzy.top/",
//发布页https://www.czzy.site/https://www.cz01.vip/
"请求头": "User-Agent$Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36 GLS/100.10.9939.100#Cookie$myannoun=1;sl-session=nifXAZvt5WjqlDh/NcYTUA==;sl-challenge-server=cloud;sl_jwt_session=EQveYsYDV7wH/Wphi/tHVo2pAgUUX3uSIMZ9fWDJtT4OJI8j22NuLwc8mqCbW1a1;sl_jwt_sign=;wordpress_logged_in_748088ce97a4ca7fd21a7d585d745ae0=mimang%7C1759985581%7COXGZlXfKhdGnvczyTtiNwPyeBrEG3eXSJ5t7nZiG3zU%7C6080b1ef7e3be9093358dd9a14d9b1c33a8a3636aa2df11a2bd4b328048b52bb#Referer$https://czzy.top/",
"二次截取":"<div class=\"bt_img mi_ne_kd mrb\">&&<div class=\"pagenavi_txt\">",
"数组":"<li>&&</div>",
"图片":"data-original=\"&&\"",
"标题":"alt=\"&&\"",
"链接":"href=\"&&\"",
"登陆":"https://czzy.top/api/vs/session;post;[email protected]&password=123456789&email=&url=https://czzy.top/&invitecode=&linuser=",
"副标题":"qb\">&&</span>",
"线路数组":"<div class=\"mi_paly_box\">&&</div>",
"线路标题":"<span>&&</span>",
"播放数组":"<div class=\"paly_list_btn\">&&</div>",
"状态":"上映:&&</li>",
"导演":"导演&&</li>",
"主演":"主演&&</li>",
"简介":"<div class=\"yp_context\">&&</p>",
"播放列表":"<a&&/a>",
"播放标题":">&&<",
"播放链接":"href=\"&&\"",
"跳转播放链接":"<iframe*src=\"&&\"",
"二次跳转播放链接":"cons*svg = '&&'[工具:unicode]",
//"搜索url": "https://cn.bing.com/search?q={wd}czzy88&FPIG=C048985DE9C84650BBC515F10F1AF60F&first=10&FORM=PERE&cc=tw",
//"搜索请求头": "User-Agent$Mozilla/5.0 (Linux; Android 13; SM-A037U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Mobile Safari/537.36 uacq",
"搜索url":"https://czzy.top/boss1O1?q={wd}",
// "搜索数组": "<div class=\"VanillaReact OrganicTitle OrganicTitle_multiline Typo Typo_text_l organic__title-wrapper\"&&</h2>",
//"搜索标题":"role=\"text\">&&》[替换:</b>>>空<b>>>空]",
//"搜索链接":"href=\"&&\"",
"搜索模式":"1",
"搜索二次截取":"<div class=\"bt_img mi_ne_kd search_list\">&&</li>",
"搜索数组":"<li>&&</a>",
"搜索图片":"src=\"&&\"",
"搜索标题":"alt=\"&&\"",
"搜索链接":"href=\"&&\"",
//"搜索副标题":"class=\"jidi\"><span>&&</span>",
"搜索副标题":"alt=\"&&\"",
"嗅探词":"ssrcdn.com#ctyunxs#124.223.74.47#.m3u8#.mp4#obj/",
//"过滤词":"url=#py1080p.com#cnzz.com#baidu.com#bilibili.com",
"播放请求头":"User-Agent$Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36 GLS/100.10.9939.100#Cookie$myannoun=1;sl-challenge-server=cloud;sl-session=oellDmtwrGgTj59GoKOZMg==",
"分类":"国产剧&最新电影&电影&连续剧",
"分类值":"gcj&zuixindianying&movie_bt/movie_bt_series/dyy&dsj",
"分类url":"https://czzy.top/{cateId}/page/{catePg};;P",
"筛选":"0"
}
{
"作者": "🐰兔爷🐇",
"站名": "厂长资源",
"编码": "UTF-8",
"发布地址": "https://www.cz01.vip/",
"请求头": "User-Agent$MOBILE_UA",
"主页url": "https://czzyv.com/",
"首页": "200",
"起始页": "1",
"分类url": "/{cateId}/page/{catePg};;rcRA",
"分类": "豆瓣电影Top250$dbtop250#最新电影$zuixindianying#剧场版$dongmanjuchangban#电影$movie_bt/movie_bt_series/dyy#电视剧$movie_bt/movie_bt_series/dianshiju#俄罗斯电影$movie_bt/movie_bt_series/eluosidianying#加拿大电影$movie_bt/movie_bt_series/jianadadianying#动画$movie_bt/movie_bt_series/dohua#华语电影$movie_bt/movie_bt_series/huayudianying#印度电影$movie_bt/movie_bt_series/yindudianying#国产剧$movie_bt/movie_bt_series/guochanju#日剧$movie_bt/movie_bt_series/rj#日本电影$movie_bt/movie_bt_series/ribendianying#欧美电影$movie_bt/movie_bt_series/meiguodianying#海外剧(其他)$movie_bt/movie_bt_series/hwj#美剧$movie_bt/movie_bt_series/mj#韩剧$movie_bt/movie_bt_series/hj#韩国电影$movie_bt/movie_bt_series/hanguodianying#番剧$fanju",
"数组": "<li><a&&</a></h",
"图片": "data-original=\"&&\"",
"标题": "alt=\"&&\"",
"副标题": "jidi\"><span>&&<+-+furk\">&&<",
"链接": "href=\"&&\"",
"影片年代": "年份&&</li",
"影片地区": "地区&&</li",
"影片类型": "类型:&&</li",
"状态": "上映:&&</li",
"导演": "导演:&&</li",
"主演": "主演:&&</li",
"简介": "👶+yp_context\">&&</div",
"线路数组": "<div class=\"ypxingq&&</div",
"线路标题": "厂长专线",
"播放数组": "<div class=\"paly_list_btn&&</div",
"播放列表": "<a&&/a>",
"播放标题": ">&&<",
"播放链接": "href=\"&&\"",
"搜索url": "/daoyongjiek0shibushiyoubing?q={wd}&f=_all&p={pg}",
"搜索模式": "1",
"筛选": "1"
}
+21
View File
@@ -0,0 +1,21 @@
{
"站名": "多瑙影院",
"时间": "20260306",
"请求头": "",
"主页url": "https://dnvod.org/",
"首页": "100",
"数组": "默认--<a&&</a>[包含:detail#src=]||首页--<a&&</span[包含:detail#src=]",
"图片": "src=\"&&\"",
"标题": "text-dark\">&&<",
"链接": "href=\"&&\"",
"搜索url": "https://dnvod.org/search?q={wd}&page={catePg}",
"搜索数组": "<a&&class=\"p[包含:detail#src=]",
"搜索图片": "src=\"&&\"",
"搜索标题": "text-dark\">&&<",
"搜索链接": "href=\"&&\"",
"简介": "keywords\" content=\"&&\"",
"分类url": "https://dnvod.org/{cateId}/list/?year={year}&region={area}&page={catePg}",
"分类": "电视剧$tv#电影$movie#动漫$anime#综艺$show"
}
@@ -0,0 +1,57 @@
{
"title": "星辰影院",
"author": "御清弦",
"Headers": "PC_UA",
"PicNeedProxy": "0",
"homeContent": "1",
"rcmed_url": "https://www.xkxd.cc/",
"home_arr_rule": ".myci-vodlist&&li",
"hmepi_arr_rule": ".myci-vodlist__box",
"home_is_jsoup": "1",
"firstpage": "1",
"class_url": "https://www.xkxd.cc/vod/{catePg}/{cateId}/0/0/0/0/0/0[firstPage=https://www.xkxd.cc/vod/1/{cateId}/0/0/0/0/0/0]",
"class_name": "电影&电视剧&综艺&动漫&短剧",
"class_value": "39&40&41&42&195",
"filterdata": {},
"cat_mode": "1",
"cat_arr_rule": ".myci-vodlist&&li",
"cat_is_jsoup": "1",
"cat_title": ".myci-vodlist__detail&&.title&&a&&Text",
"cat_url": ".myci-vodlist__box&&a&&href",
"cat_pic": ".myci-vodlist__thumb&&data-original",
"cat_prefix": "https://www.xkxd.cc",
"SHeaders": "User-Agent$PC_UA",
"search_url": "https://www.xkxd.cc/public/auto/search1.html?keyword={wd}",
"sea_PtBody": "",
"search_mode": "1",
"sea_arr_rule": ".myci-vodlist__media&&li",
"sea_is_jsoup": "1",
"sea_pic": ".myci-vodlist__thumb&&data-original",
"sea_title": ".title&&a&&Text",
"sea_url": ".thumb&&a&&href",
"search_prefix": "https://www.xkxd.cc",
"force_play": "0",
"play_suffix": "#isVideo=true#",
"play_header": "authority$ku.peizq.online#Referer$https://play.peizq.online",
"proj_is_jsoup": "1",
"proj_cate": ".myci-content__detail&&p:contains(类型:)&&a&&Text",
"proj_year": ".myci-content__detail&&p:contains(年份:)&&a&&Text",
"proj_area": ".myci-content__detail&&p:contains(地区:)&&a&&Text",
"proj_actor": ".myci-content__detail&&p:contains(主演:)&&span&&Text",
"proj_plot": ".myci-content__detail&&p:contains(简介:)&&span.desc_info&&Text",
"list_arr_rule": ".myci-pannel-box.playlist",
"epi_arr_rule": ".myci-content__playlist&&li a",
"epi_title": "Text",
"epi_url": "href",
"epi_reverse": "0",
"epiurl_prefix": "https://www.xkxd.cc",
"Anal_MacPlayer": "0",
"ManualSniffer": "1",
"VideoFormat": ".mp4#.m3u8#.flv#player/m3u8",
"VideoFilter": ".html#=http"
}
@@ -0,0 +1,57 @@
{
"作者": "",
"站名": "明星优质埃及影院",
"发布页": "发布页uzvod.com https://hrvod.com https://yevod.com https://quvod.com https://bsvod.com",
//MXVOD 明星影院-在线电影-mxvid.com https://ucvod.com https://yevod.com https://quvod.com https://hrvod.com
//明星影院--优质影院--iGVOD 埃及影院-免费电影在线观看igvod.com https://hrvod.com https://yevod.com https://quvod.com https://bsvod.com
"请求头": "User-Agent$MOBILE_UA",
"编码": "UTF-8",
"图片代理": "",
"直接播放": "0",
"播放请求头": "",
"过滤词": "",
"主页url": "https://mxvid.com/",
"首页": "120",
"起始页": "1",
"分类": "电影&电视剧&综艺&动漫&短剧",
"分类值": "dianying&dianxuju&zongyi&dongman&duanju",
"分类url": "https://mxvid.com/vodshow/{cateId}-{area}-{by}-{class}-{lang}-{letter}---{catePg}---{year}.html",
"二次截取": "module-items\"&&id=\"page",
"数组": "lazyloaded&&/a>",
"标题": "title=*>&&<",
"图片": "data-src=\"&&\"",
"副标题": "class\">&&<",
"链接": "href=\"&&\"[替换:vodplay>>voddetail#-1-1.html>>.html]",
"影片年代": "-----------*.html\">&&</",
"影片地区": "video:area\" content=\"&&\"",
"影片类型": "video:class\" content=\"&&\"",
"状态": "tag-link-red\">&&</div>",
"导演": "导演:&&</div>",
"主演": "主演:&&\">",
"简介": "vod_content\"&&</div>",
"线路数组": "data-dropdown&&/small>[替换:推荐>>空]",
"线路标题": "value=\"&&\"+【共+<small>&&<+集】",
"播放数组": "id=\"sort-item&&</div>",
"播放列表": "<a&&/a>",
"播放标题": "<span>&&<",
"播放链接": "href=\"&&\"",
"跳转播放链接": "var player_*\"url\":\"&&\"",
"搜索请求头": "User-Agent$MOBILE_UA",
"搜索url": "https://mxvid.com/vodsearch/{cateId}-{area}-{by}-{class}-{lang}-{letter}---{catePg}---{year}.html?wd={wd}",
"搜索模式": "1",
//"搜索数组": "lazyload\"&&/a>",
//"搜索标题": "title=\"&&\"",
"搜索图片": "data-src=\"&&\"",
"搜索副标题": "title=*>&&<",
"搜索链接": "href=\"&&\"",
"筛选": "1",
"类型": "动作片$dongzuopian#喜剧片$xijupian#爱情片$aiqingpian#科幻片$kehuanpian#恐怖片$kongbupian#战争片$zhanzhengpian#剧情片$juqingpian#动画片$donghuapian#悬疑片$xuanyi#纪录片$jilupian#奇幻片$qihuanpian#灾难片$zainanpian||国产剧$guochanju#欧美剧$oumeiju#日剧$riju#韩剧$hanju#港台剧$gangtai#海外剧$haiwai||大陆综艺$daluzongyi#港台综艺$gangtaizongyi#欧美综艺$oumeizongyi#日韩综艺$rihanzongyi#海外综艺$haiwaizongyi||国产动漫$guochandongman#日韩动漫$rihandongman#欧美动漫$oumeidongman#海外动漫$haiwaidongman||空",
"剧情": "喜剧&爱情&恐怖&动作&科幻&剧情&战争&警匪&犯罪&动画&奇幻&武侠&冒险&枪战&恐怖&悬疑&惊悚&经典&青春&文艺&微电影&古装&历史&运动&农村&儿童&网络电影||古装&战争&青春偶像&喜剧&家庭&犯罪&动作&奇幻&剧情&历史&经典&乡村&情景&商战&网剧&其他||选秀&情感&访谈&播报&旅游&音乐&美食&纪实&曲艺&生活&游戏互动&财经&求职||情感&科幻&热血&推理&搞笑&冒险&萝莉&校园&动作&机战&运动&战争&少年&少女&社会&原创&亲子&益智&励志&其他||古装&虐恋&逆袭&神豪&重生&复仇&穿越&甜宠&强者&萌宝&其它",
"年份": "1990-2025",
"年份值": "*",
"语言值": "*",
"排序": "时间&人气&评分",
"排序值": "time&hits&score"
}
+19
View File
@@ -0,0 +1,19 @@
{
"作者":"20260406",
"站名":"泥视频",
"主页url":"https://www.nivod.cc",
"数组":"<li&&</li>[不包含:泥视频]",
"图片": "默认--https://www.nivod.cc+url(&&)||首页--src=\"&&\"",
"标题":"title=\"&&\"",
"链接":"href=\"&&\"",
"搜索url":"https://www.nivod.cc/search_x.html?keyword={wd}&sign=c8ec6c33",
"搜索模式":"1",
"倒序":"1",
"分类url": "https://www.nivod.cc/filter.html?channel={cateId}&region={area}&showtype={class}&year={year}&page={catePg}",
"分类": "电影$movie#电视剧$tv#综艺$show#动漫$anime"},
"header": {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36 Edg/136.0.0.0"}
}
+17
View File
@@ -0,0 +1,17 @@
{
"站名": "火车太堵20260323",
"请求头": "手机",
"主页url":"https://www.tdgo.shop/",
"二次截取": "module-main module-page&&<div id=\"page\">",
"数组": "<a&&</a>[包含:/voddetail/]",
"图片": "data-original=\"&&\"",
"标题":"title=\"&&\"",
"链接":"href=\"&&\"",
"简介": "description\" content=\"&&\"",
"搜索url":"/vodsearch/{wd}----------{pg}---.html",
"搜索模式":"1",
"分类":"电影$20#连续剧$21#综艺$23#动漫$22#短剧$24",
"分类url": "https://www.tdgo.shop/vodshow/{cateId}-{area}-------{catePg}---{year}.html"
}
+16
View File
@@ -0,0 +1,16 @@
{
"作者":"20260317",
"站名":"看戏影视--看戏网--看戏影院https://www.wokanxi.com/ https://www.kanxis.com/ https://www.kanxiya.com/ www.wokanxi.com/ www.kanxiwa.com/ www.ikanxi.com/ www.kanxixi.com",
"数组": "<li>&&</li>",
"图片": "data-original=\"&&\"",
"标题": "title=\"&&\"",
"副标题": "text-right\">&&</span>",
"链接": "href=\"&&\"",
"搜索url":"https://www.kxyes.com/search/{wd}--------{catePg}---{year}.html",
"搜索模式":"1",
"分类url":"https://www.kxyes.com/tags/{cateId}--------{catePg}---{year}.html;;",
"分类": "电影$1#电视剧$2#综艺$3#动漫$4"
}
+23
View File
@@ -0,0 +1,23 @@
{
//注意:图片加载有bug 就这样吧
"作者":"御清弦",
"站名":"策驰影院",
"主页url":"https://www.erkys.com/",
"简介":"提醒您请勿相信广告,以免上当!+description\" content=\"&&\">",
"搜索url":"https://www.erkys.com/vodsearch/_____________.html?wd={wd}&submit=",
"搜索后缀":"/video/",
"搜索模式":"1",
"搜索数组":"class=\"stui-vodlist__thumb&&</li>",
"搜索图片":"data-original=\"&&\"",
"搜索图片前缀":"https://www.erkys.com",
"搜索标题":"title=\"&&\"",
"搜索链接":"href=\"&&\"",
"搜索链接前缀": "https://www.erkys.com",
"搜索副标题":"pic-text text-right\">&&</span>",
"分类": "电影&电视剧&动漫&综艺&短剧",
"分类值": "1&2&3&4&5",
"分类url": "https://www.erkys.com/type/{cateId}/page/{catePg}.html[https://www.erkys.com/type/{cateId}.html]"
//看剧网http://waps.bjzknj.com/
}
+11
View File
@@ -0,0 +1,11 @@
{
"站名": "麦田影院app",
"请求头": "手机",
"发布页":"https://www.mtyy.tv/www.mtyy1.com123456789 ",
"主页url":"https://www.mtyy1.cc/",
"简介": "keywords\" content=\"&&\"",
"数组":"class=\"public-list-div public-list-bj&&</a></div></div>",
"图片":"data-src=\"&&\"",
"分类":"电影$1#连续剧$2#综艺$3#动漫$4#短剧$26",
"分类url": "https://www.mtyy9.com/vodshow/{cateId}-{area}--{class}-----{catePg}---{year}.html"
}
+1 -1
View File
@@ -11,7 +11,7 @@ from base.spider import Spider
class Spider(Spider):
def init(self, extend=""):
self.host = "https://www.mtyy5.com"
self.host = "https://www.mtyy1.cc"
self.headers = {
'User-Agent': 'Mozilla/5.0 (Linux; Android 11; MI 11) AppleWebKit/537.36 TVBox/1.0',
'Accept': 'text/html,application/xml;q=0.9,*/*;q=0.8',
+343
View File
@@ -0,0 +1,343 @@
# coding = utf-8
# !/usr/bin/python
"""
"""
from Crypto.Util.Padding import unpad
from Crypto.Util.Padding import pad
from urllib.parse import unquote
from Crypto.Cipher import ARC4
from urllib.parse import quote
from base.spider import Spider
from Crypto.Cipher import AES
from bs4 import BeautifulSoup
from base64 import b64decode
import urllib.request
import urllib.parse
import binascii
import requests
import base64
import json
import time
import sys
import re
import os
sys.path.append('..')
xurl = "https://app.whjzjx.cn"
headers = {
'User-Agent': 'Linux; Android 12; Pixel 3 XL) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.101 Mobile Safari/537.36'
}
headerf = {
"platform": "1",
"user_agent": "Mozilla/5.0 (Linux; Android 9; V1938T Build/PQ3A.190705.08211809; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/91.0.4472.114 Safari/537.36",
"content-type": "application/json; charset=utf-8"
}
times = int(time.time() * 1000)
data = {
"device": "2a50580e69d38388c94c93605241fb306",
"package_name": "com.jz.xydj",
"android_id": "ec1280db12795506",
"install_first_open": True,
"first_install_time": 1752505243345,
"last_update_time": 1752505243345,
"report_link_url": "",
"authorization": "",
"timestamp": times
}
plain_text = json.dumps(data, separators=(',', ':'), ensure_ascii=False)
key = "B@ecf920Od8A4df7"
key_bytes = key.encode('utf-8')
plain_bytes = plain_text.encode('utf-8')
cipher = AES.new(key_bytes, AES.MODE_ECB)
padded_data = pad(plain_bytes, AES.block_size)
ciphertext = cipher.encrypt(padded_data)
encrypted = base64.b64encode(ciphertext).decode('utf-8')
response = requests.post("https://u.shytkjgs.com/user/v3/account/login", headers=headerf, data=encrypted)
response_data = response.json()
Authorization = response_data['data']['token']
headerx = {
'authorization': Authorization,
'platform': '1',
'version_name': '3.8.3.1'
}
class Spider(Spider):
global xurl
global headerx
global headers
def getName(self):
return "首页"
def init(self, extend):
pass
def isVideoFormat(self, url):
pass
def manualVideoCheck(self):
pass
def extract_middle_text(self, text, start_str, end_str, pl, start_index1: str = '', end_index2: str = ''):
if pl == 3:
plx = []
while True:
start_index = text.find(start_str)
if start_index == -1:
break
end_index = text.find(end_str, start_index + len(start_str))
if end_index == -1:
break
middle_text = text[start_index + len(start_str):end_index]
plx.append(middle_text)
text = text.replace(start_str + middle_text + end_str, '')
if len(plx) > 0:
purl = ''
for i in range(len(plx)):
matches = re.findall(start_index1, plx[i])
output = ""
for match in matches:
match3 = re.search(r'(?:^|[^0-9])(\d+)(?:[^0-9]|$)', match[1])
if match3:
number = match3.group(1)
else:
number = 0
if 'http' not in match[0]:
output += f"#{match[1]}${number}{xurl}{match[0]}"
else:
output += f"#{match[1]}${number}{match[0]}"
output = output[1:]
purl = purl + output + "$$$"
purl = purl[:-3]
return purl
else:
return ""
else:
start_index = text.find(start_str)
if start_index == -1:
return ""
end_index = text.find(end_str, start_index + len(start_str))
if end_index == -1:
return ""
if pl == 0:
middle_text = text[start_index + len(start_str):end_index]
return middle_text.replace("\\", "")
if pl == 1:
middle_text = text[start_index + len(start_str):end_index]
matches = re.findall(start_index1, middle_text)
if matches:
jg = ' '.join(matches)
return jg
if pl == 2:
middle_text = text[start_index + len(start_str):end_index]
matches = re.findall(start_index1, middle_text)
if matches:
new_list = [f'{item}' for item in matches]
jg = '$$$'.join(new_list)
return jg
def homeContent(self, filter):
result = {}
result = {"class": [{"type_id": "1", "type_name": "七星剧场"},
{"type_id": "3", "type_name": "七星新剧"},
{"type_id": "2", "type_name": "七星热播"},
{"type_id": "7", "type_name": "七星星选"},
{"type_id": "5", "type_name": "七星阳光"}],
}
return result
def homeVideoContent(self):
videos = []
url= f'{xurl}/v1/theater/home_page?theater_class_id=1&class2_id=4&page_num=1&page_size=24'
detail = requests.get(url=url, headers=headerx)
detail.encoding = "utf-8"
if detail.status_code == 200:
data = detail.json()
for vod in data['data']['list']:
name = vod['theater']['title']
id = vod['theater']['id']
pic = vod['theater']['cover_url']
remark = vod['theater']['play_amount_str']
video = {
"vod_id": id,
"vod_name": name,
"vod_pic": pic,
"vod_remarks": remark
}
videos.append(video)
result = {'list': videos}
return result
def categoryContent(self, cid, pg, filter, ext):
result = {}
videos = []
url = f'{xurl}/v1/theater/home_page?theater_class_id={cid}&page_num={pg}&page_size=24'
detail = requests.get(url=url,headers=headerx)
detail.encoding = "utf-8"
if detail.status_code == 200:
data = detail.json()
for vod in data['data']['list']:
name = vod['theater']['title']
id = vod['theater']['id']
pic = vod['theater']['cover_url']
remark = vod['theater']['theme']
video = {
"vod_id": id,
"vod_name": name,
"vod_pic": pic,
"vod_remarks": remark
}
videos.append(video)
result = {'list': videos}
result['page'] = pg
result['pagecount'] = 9999
result['limit'] = 90
result['total'] = 999999
return result
def detailContent(self, ids):
did = ids[0]
result = {}
videos = []
xianlu = ''
bofang = ''
url = f'{xurl}/v2/theater_parent/detail?theater_parent_id={did}'
detail = requests.get(url=url, headers=headerx)
detail.encoding = "utf-8"
if detail.status_code == 200:
data = detail.json()
url = 'https://fs-im-kefu.7moor-fs1.com/ly/4d2c3f00-7d4c-11e5-af15-41bf63ae4ea0/1732707176882/jiduo.txt'
response = requests.get(url)
response.encoding = 'utf-8'
code = response.text
name = self.extract_middle_text(code, "s1='", "'", 0)
Jumps = self.extract_middle_text(code, "s2='", "'", 0)
content = '剧情:' + data['data']['introduction']
area = data['data']['desc_tags'][0]
remarks = data['data']['filing']
# 修复剧集只有一集的问题 - 检查theaters数据是否存在且不为空
if 'theaters' in data['data'] and data['data']['theaters']:
for sou in data['data']['theaters']:
id = sou['son_video_url']
name = sou['num']
bofang = bofang + str(name) + '$' + id + '#'
bofang = bofang[:-1] if bofang.endswith('#') else bofang
xianlu = '七星'
else:
# 如果没有theaters数据,检查是否有单个视频URL
if 'video_url' in data['data'] and data['data']['video_url']:
bofang = '1$' + data['data']['video_url']
xianlu = '七星'
else:
bofang = Jumps
xianlu = '1'
videos.append({
"vod_id": did,
"vod_content": content,
"vod_remarks": remarks,
"vod_area": area,
"vod_play_from": xianlu,
"vod_play_url": bofang
})
result['list'] = videos
return result
def playerContent(self, flag, id, vipFlags):
result = {}
result["parse"] = 0
result["playUrl"] = ''
result["url"] = id
result["header"] = headers
return result
def searchContentPage(self, key, quick, page):
result = {}
videos = []
payload = {
"text": key
}
url = f"{xurl}/v3/search"
detail = requests.post(url=url, headers=headerx, json=payload)
if detail.status_code == 200:
detail.encoding = "utf-8"
data = detail.json()
for vod in data['data']['theater']['search_data']:
name = vod['title']
id = vod['id']
pic = vod['cover_url']
remark = vod['score_str']
video = {
"vod_id": id,
"vod_name": name,
"vod_pic": pic,
"vod_remarks": remark
}
videos.append(video)
result['list'] = videos
result['page'] = page
result['pagecount'] = 9999
result['limit'] = 90
result['total'] = 999999
return result
def searchContent(self, key, quick, pg="1"):
return self.searchContentPage(key, quick, '1')
def localProxy(self, params):
if params['type'] == "m3u8":
return self.proxyM3u8(params)
elif params['type'] == "media":
return self.proxyMedia(params)
elif params['type'] == "ts":
return self.proxyTs(params)
return None
+330
View File
@@ -0,0 +1,330 @@
# -*- coding: utf-8 -*-
# by @嗷呜
import json
import random
import sys
from base64 import b64encode, b64decode
from concurrent.futures import ThreadPoolExecutor
# 引入 RSA 加解密所需模块
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
sys.path.append('..')
from base.spider import Spider
class Spider(Spider):
def init(self, extend=""):
did = self.getdid()
self.headers.update({'deviceId': did})
token = self.gettk()
self.headers.update({'token': token})
def getName(self):
pass
def isVideoFormat(self, url):
pass
def manualVideoCheck(self):
pass
def destroy(self):
pass
# 1. 修改为主机域名
host = 'http://qkys.qukanwh.com'
# 2. 同步原脚本的配置请求头
headers = {
'HOST': 'qkys.qukanwh.com',
'User-Agent': 'okhttp/4.12.0',
'client': 'app',
'deviceType': 'Android',
'Referer': ''
}
# 3. 导入原脚本中的 RSA 密钥对与配置
publicKey_str = "-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCoYt0BP77U+DM08BiI/QbSRIfxijXo85BTPqIM1Ow8BNwhLETzRIZ+dEwdWDbydG/PspgBAfRpGaYVdJYtvaC2JnoO8+Ik6qMWojfEJxSFLa0Pb0A892tun4gsxoEMjcreZ+YGyaBxAfqX0BSMfdrOgIYaZQjYrw9TRLlUT31QoQIDAQAB\n-----END PUBLIC KEY-----"
privateKey_str = "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCquQQ5r6+yJI8CDFkXRp8vUsdD45ov8EP12ooLs56ca2DQXaSNGS9910bAPVA9chkp0mKIvKqjAsHz5Tl9EeNPblarGEeJUIxpxZtiSqNTpvtiD/TjhpzuHYic7RAfQ/h7p/ypE8ymU42pYjsB5t26Mv6XgkLV+jzrSf73HlCuS0iMyLmt6zz3Mw9izM13EpB8iFLtfbbYymycKTx4RAmPQLwhNGex/AlUIYxXP4R2yyaa4W6mEtc6aME2QuzJFxPgP3HJ9NBx/LWVn4skxWjZ7zg+VRQRHnjyVaSLu3Z5gN5ITWCyE32qaHJa6WBahZj5jWhRyAG1bQ+xKJa8lBL5AgMBAAECggEAUwv9SjJ0PSwbhNuM2w23kcWquROWhYtTA91zGY4esehqB/IFgb2mpIh8Gje5OKqwIu/8jpd4SiOlRYdUF8sD0DfUYRZGdj2AkFNX6tBz8tVfo6wvbB6naA1lzzBij1L5JO3qsjS3cJFkb+kg2yP66AC2Z+0tpfk8eRhdtshAZwfcd1DEGt1uAvYL1eaUK9HRvpt9lPeGcHERDl2hBd4uyaF0K1O+zF9y59nYbTySWPxRZq3sFEE85xRMlstD7YZi7W2gKvMFRD4/FKmrZ3m7aKJRITtyKOyyPcYmepNv3Qv7kk59Pg38n2WWQ0Ra/bCH3E48YNCnQvZMpitkTfJhoQKBgQDbnROOYTP8OTJ6f/qhoGjxeO3x1VOaOp8l0x7b0SCfoqNGS0Cyiqj72BmJtPMPqSTjn6MmNzqbg1KOdhXyzNozs+i5ccW1M56j96mr5I/Z0FpE3oyIHNfDDBlf9M8YQqEF9oYxniYYft9oapO7cRQkHER6qpvnHTavwlv4m78CXwKBgQDHAjs2YlpKDdI1lcbZJCc7TwtH+Pd2bUki8YXafWNcPhITQHbOZjr310eK1QJC6GJncjkOqbX7yv3ivvTO35FZTQhuA1xEG1P00FG8bE0tHYPIwQHi9y0eA5cieMdo8E6XYria1mw/3fqSQEsfZyJlR32JQIoGAipM8iO1X2nZpwKBgDkMFIhnt5lNQk+P7wsNIDWZtDWdtJnboHuy29E+Abt2A/O+mI/IdRz2hau/1WO8DFkUnszOi+rZshhPlGP90rCbi1igtTrcrdjp/KkqNjPea5R4OwkgdOu1uOG0NheXNzzVTQaWjk7Opjn5dWa7eP/oV+GFb/oZHJuLYVizHGsBAoGADA7rjZEKDYCm4w5PPSr+oY5ZjaPdQrS+gLqHtMRyN82fBMGcMUdqfUfzEstzVqCEDeaS5HuOBlK3bXzKkppjUTjksN3NQmcxgBz7RuJ9DqXCLXDcb2cwuafYCYOt+YLOEEgwDVm+t2P44dG5e46hO+fICH/7nP+WlpD5buz4GfMCgYB57r3g/6hi9WUDnfc7ZAzWMqR0EhJVYKYy+KFEtdIPzhkkIHq5RASe88E9kzoGoZFdb3tIjvGZWcHerirrqWkMsuQtP/Qi0zjieid5tAPj+r4kbiCVTw0E0jnmPBzGInQi7lpeTTKnG1fbyS5lBS+WmHfIuzpECgCkxhaT+LJJkg==\n-----END PRIVATE KEY-----"
# RSA 公钥加密实现
def rsa_encrypt(self, text):
try:
key = RSA.import_key(self.publicKey_str)
cipher = PKCS1_v1_5.new(key)
cipher_text = cipher.encrypt(text.encode('utf-8'))
return b64encode(cipher_text).decode('utf-8')
except Exception as e:
print(f"RSA加密失败: {e}")
return ""
# RSA 私钥解密实现
def rsa_decrypt(self, text):
try:
key = RSA.import_key(self.privateKey_str)
cipher = PKCS1_v1_5.new(key)
raw_bytes = b64decode(text.encode('utf-8'))
decrypted = b""
offset = 0
while offset < len(raw_bytes):
chunk = raw_bytes[offset:offset + 256]
decrypted += cipher.decrypt(chunk, None)
offset += 256
return decrypted.decode('utf-8')
except Exception as e:
print(f"RSA解密失败: {e}")
return ""
def homeContent(self, filter):
data = self.post(f"{self.host}/api/v1/app/screen/screenType", headers=self.headers).json()
result = {}
cate = {
"类型": "type",
"地区": "area",
"年份": "year"
}
sort = {
'key': 'sort',
'name': '排序',
'value': [{'n': '最新', 'v': 'NEWEST'}, {'n': '热门', 'v': 'HOT'}, {'n': '收藏', 'v': 'COLLECT'}]
}
classes = []
filters = {}
for k in data.get('data', []):
classes.append({
'type_name': k['name'],
'type_id': str(k['id'])
})
filters[str(k['id'])] = []
for v in k.get('children', []):
if v['name'] in cate:
filters[str(k['id'])].append({
'name': v['name'],
'key': cate[v['name']],
'value': [{'n': i['name'], 'v': i['name']} for i in v.get('children', [])]
})
filters[str(k['id'])].append(sort)
result['class'] = classes
result['filters'] = filters
return result
def homeVideoContent(self):
jdata = {
"condition": {
"sreecnTypeEnum": "NEWEST"
},
"pageNum": 1,
"pageSize": 40
}
data = self.post(f"{self.host}/api/v1/app/screen/screenMovie", headers=self.headers, json=jdata).json()
return {'list': self.getlist(data.get('data', {}).get('records', []))}
def categoryContent(self, tid, pg, filter, extend):
# 保持最纯粹的条件字段,移除任何空字符串占位
condition = {
'sreecnTypeEnum': 'NEWEST',
'typeId': int(tid) if str(tid).isdigit() else tid
}
if extend:
if 'sort' in extend:
condition['sreecnTypeEnum'] = extend.pop('sort')
condition.update(extend)
jdata = {
'condition': condition,
'pageNum': int(pg),
'pageSize': 40,
}
try:
data = self.post(f"{self.host}/api/v1/app/screen/screenMovie", headers=self.headers, json=jdata).json()
result = {}
if data and data.get('data') and 'records' in data['data']:
result['list'] = self.getlist(data['data']['records'])
else:
result['list'] = []
result['page'] = pg
result['pagecount'] = 9999
result['limit'] = 40
result['total'] = 999999
return result
except Exception as e:
print(f"分类获取错误: {e}")
return {'list': [], 'page': pg}
def detailContent(self, ids):
ids = ids[0].split('@@')
jdata = {"id": int(ids[0]), "typeId": ids[-1]}
v = self.post(f"{self.host}/api/v1/app/play/movieDesc", headers=self.headers, json=jdata).json()
v = v.get('data', {})
vod = {
'type_name': v.get('typeId', ''),
'vod_year': v.get('year', ''),
'vod_area': v.get('area', ''),
'vod_actor': v.get('star', ''),
'vod_director': v.get('director', ''),
'vod_content': v.get('introduce', ''),
'vod_play_from': '',
'vod_play_url': ''
}
play_params = {
"id": int(ids[0]),
"source": 0,
"typeId": ids[-1]
}
encrypt_payload = {"key": self.rsa_encrypt(json.dumps(play_params))}
c_res = self.post(f"{self.host}/api/v1/app/play/movieDetails", headers=self.headers, json=encrypt_payload).json()
decrypted_play_str = self.rsa_decrypt(c_res.get('data', ''))
if not decrypted_play_str:
return {'list': [vod]}
decrypted_play_data = json.loads(decrypted_play_str)
l = decrypted_play_data.get('moviePlayerList', [])
if not l:
return {'list': [vod]}
n = {str(i['id']): i['moviePlayerName'] for i in l}
m = play_params.copy()
m.update({'playerId': l[0]['id']})
first_source_payload = {"key": self.rsa_encrypt(json.dumps(m))}
first_res = self.post(f"{self.host}/api/v1/app/play/movieDetails", headers=self.headers, json=first_source_payload).json()
decrypted_first_str = self.rsa_decrypt(first_res.get('data', ''))
if decrypted_first_str:
decrypted_first_episode = json.loads(decrypted_first_str)
pd = self.getv(m, decrypted_first_episode.get('episodeList', []))
else:
pd = {}
if len(l) > 1:
with ThreadPoolExecutor(max_workers=len(l)-1) as executor:
future_to_player = {executor.submit(self.getd, play_params, player): player for player in l[1:]}
for future in future_to_player:
try:
o, p = future.result()
if p:
pd.update(self.getv(o, p))
except Exception as e:
print(f"多线路请求失败: {e}")
w, e = [], []
for i, x in pd.items():
if x:
w.append(n.get(i, '未知线路'))
e.append(x)
vod['vod_play_from'] = '$$$'.join(w)
vod['vod_play_url'] = '$$$'.join(e)
return {'list': [vod]}
def searchContent(self, key, quick, pg="1"):
jdata = {
"condition": {
"value": str(key)
},
"pageNum": int(pg),
"pageSize": 40
}
try:
data = self.post(f"{self.host}/api/v1/app/search/searchMovie", headers=self.headers, json=jdata).json()
return {'list': self.getlist(data.get('data', {}).get('records', [])), 'page': pg}
except Exception as e:
print(f"搜索请求失败: {e}")
return {'list': [], 'page': pg}
def playerContent(self, flag, id, vipFlags):
raw_id_str = self.d64(id)
if not raw_id_str:
return {'parse': 0, 'url': ''}
jdata = json.loads(raw_id_str)
encrypt_payload = {"key": self.rsa_encrypt(json.dumps(jdata))}
data = self.post(f"{self.host}/api/v1/app/play/movieDetails", headers=self.headers, json=encrypt_payload).json()
try:
decrypted_url_data = json.loads(self.rsa_decrypt(data.get('data', '')))
playerUrl = decrypted_url_data.get('url', '')
if not playerUrl:
return {'parse': 0, 'url': ''}
params = {'playerUrl': playerUrl, 'playerId': jdata['playerId']}
pd = self.fetch(f"{self.host}/api/v1/app/play/analysisMovieUrl", headers=self.headers, params=params).json()
url, p = pd.get('data', ''), 0
except Exception as e:
print(f"解析流媒体直链失败: {e}")
url, p = "", 0
return {'parse': p, 'url': url, 'header': {'User-Agent': 'okhttp/4.12.0'}}
def localProxy(self, param):
pass
def liveContent(self, url):
pass
def gettk(self):
self.headers.update({'deviceId': self.getdid()})
try:
data = self.fetch(f"{self.host}/api/v1/app/user/visitorInfo", headers=self.headers).json()
return data.get('data', {}).get('token', '')
except:
return ""
def getdid(self):
did = self.getCache('ldid')
if not did:
hex_chars = '0123456789abcdef'
did = ''.join(random.choice(hex_chars) for _ in range(16))
self.setCache('ldid', did)
return did
def getd(self, jdata, player):
x = jdata.copy()
x.update({'playerId': player['id']})
encrypt_payload = {"key": self.rsa_encrypt(json.dumps(x))}
response = self.post(f"{self.host}/api/v1/app/play/movieDetails", headers=self.headers, json=encrypt_payload).json()
decrypted_str = self.rsa_decrypt(response.get('data', ''))
if decrypted_str:
decrypted_episode = json.loads(decrypted_str)
return x, decrypted_episode.get('episodeList', [])
return x, []
def getv(self, d, c):
f = {str(d['playerId']): ''}
g = []
for i in c:
j = d.copy()
j.update({'episodeId': i['id']})
g.append(f"{i['episode']}${self.e64(json.dumps(j))}")
f[str(d['playerId'])] = '#'.join(g)
return f
def getlist(self, data):
videos = []
for i in data:
if not i.get('id'):
continue
videos.append({
'vod_id': f"{i['id']}@@{i.get('typeId', '')}",
'vod_name': i.get('name', ''),
'vod_pic': i.get('cover', ''),
'vod_year': i.get('year', ''),
'vod_remarks': i.get('totalEpisode', '')
})
return videos
def e64(self, text):
try:
return b64encode(text.encode('utf-8')).decode('utf-8')
except:
return ""
def d64(self, encoded_text):
try:
return b64decode(encoded_text.encode('utf-8')).decode('utf-8')
except:
return ""
+502
View File
@@ -0,0 +1,502 @@
# -*- coding: utf-8 -*-
# 修复:歌手不显示歌手图片
# by:垃圾星河
# 代码指导:嗷呜呜呜呜
# 增加:自动人机验证绕过
import re
import sys
import time
from base64 import b64encode, b64decode
from urllib.parse import quote, unquote
from pyquery import PyQuery as pq
from requests import Session, adapters
from urllib3.util.retry import Retry
from concurrent.futures import ThreadPoolExecutor, as_completed
sys.path.append('..')
from base.spider import Spider
class Spider(Spider):
def init(self, extend=""):
self.host = "https://www.22a5.com"
self.session = Session()
adapter = adapters.HTTPAdapter(
max_retries=Retry(total=3, backoff_factor=0.5, status_forcelist=[429, 500, 502, 503, 504]),
pool_connections=20,
pool_maxsize=50
)
self.session.mount("http://", adapter)
self.session.mount("https://", adapter)
self.headers = {
"User-Agent": "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36"
}
self.session.headers.update(self.headers)
def getName(self):
return "爱听音乐"
def isVideoFormat(self, url):
return bool(re.search(r'\.(m3u8|mp4|mp3|m4a|flv)(\?|$)', url or "", re.I))
def manualVideoCheck(self):
return False
def destroy(self):
self.session.close()
# ==================== 新增人机验证绕过 ====================
def _bypass_verification(self, url, response_text):
"""若当前页面是人机验证,自动提交勾选"""
if '安全人机验证' not in response_text and 'human_check' not in response_text:
return None
# 提取 csrf_token(支持多种格式)
token_match = re.search(r'name="csrf_token"\s+value="([^"]+)"', response_text)
if not token_match:
print("[爱听音乐] 未找到 csrf_token,跳过绕过")
return None
token = token_match.group(1)
# 构造提交数据
data = {
'csrf_token': token,
'human_check': 'on'
}
try:
# 发送 POST 请求,自动跟随重定向
post_resp = self.session.post(url, data=data, allow_redirects=True, timeout=10)
print("[爱听音乐] 人机验证已绕过")
return post_resp
except Exception as e:
print(f"[爱听音乐] 人机验证提交失败: {e}")
return None
def getpq(self, url):
"""获取页面并自动处理人机验证(重试3次)"""
full_url = self._abs(url)
for attempt in range(3):
try:
resp = self.session.get(full_url, timeout=5)
# 若遇到验证页,尝试绕过
if '安全人机验证' in resp.text or 'human_check' in resp.text:
print("[爱听音乐] 检测到人机验证,尝试自动绕过...")
bypass_resp = self._bypass_verification(full_url, resp.text)
if bypass_resp:
# 验证成功后,返回最终页面(可能是重定向后的目标)
return pq(bypass_resp.text)
else:
# 绕过失败,等待后重试
time.sleep(1)
continue
else:
# 正常页面直接返回
return pq(resp.text)
except Exception as e:
print(f"[爱听音乐] 请求失败 (尝试 {attempt+1}/3): {e}")
time.sleep(0.5 * (attempt + 1))
# 全部失败,返回空文档
return pq("<html></html>")
# ==================== 原有功能(保持不变) ====================
def homeContent(self, filter):
classes = [
{"type_name": n, "type_id": i}
for n, i in [
("歌手", "/singerlist/index/index/index/index.html"),
("TOP榜单", "/list/top.html"),
("新歌榜", "/list/new.html"),
("电台", "/radiolist/index.html"),
("高清MV", "/mvlist/oumei.html"),
("专辑", "/albumlist/index.html"),
("歌单", "/playtype/index.html")
]
]
filters = {}
for p in [c["type_id"] for c in classes if "singer" not in c["type_id"]]:
d = self._fetch_filters(p)
if d:
filters[p] = d
if "/radiolist/index.html" not in filters:
filters["/radiolist/index.html"] = [{
"key": "id",
"name": "分类",
"value": [
{"n": n, "v": v}
for n, v in zip(
["最新", "最热", "有声小说", "相声", "音乐", "情感", "国漫", "影视", "脱口秀", "历史", "儿童", "教育", "八卦", "推理", "头条"],
["index", "hot", "novel", "xiangyi", "music", "emotion", "game", "yingshi", "talkshow", "history",
"children", "education", "gossip", "tuili", "headline"]
)
]
}]
filters["/singerlist/index/index/index/index.html"] = [
{
"key": "area",
"name": "地区",
"value": [
{"n": "全部", "v": "index"},
{"n": "华语", "v": "huayu"},
{"n": "欧美", "v": "oumei"},
{"n": "韩国", "v": "hanguo"},
{"n": "日本", "v": "ribrn"}
]
},
{
"key": "sex",
"name": "性别",
"value": [
{"n": "全部", "v": "index"},
{"n": "", "v": "male"},
{"n": "", "v": "girl"},
{"n": "组合", "v": "band"}
]
},
{
"key": "genre",
"name": "流派",
"value": [
{"n": "全部", "v": "index"},
{"n": "流行", "v": "liuxing"},
{"n": "电子", "v": "dianzi"},
{"n": "摇滚", "v": "yaogun"},
{"n": "嘻哈", "v": "xiha"},
{"n": "R&B", "v": "rb"},
{"n": "民谣", "v": "minyao"},
{"n": "爵士", "v": "jueshi"},
{"n": "古典", "v": "gudian"}
]
}
]
return {"class": classes, "filters": filters, "list": []}
def homeVideoContent(self):
return {"list": []}
def categoryContent(self, tid, pg, filter, extend):
pg = int(pg or 1)
url = tid
if "/singerlist/" in tid:
parts = tid.split('/')
if len(parts) >= 6:
url = "/".join(parts[:2] + [extend.get(k, parts[i]) for i, k in enumerate(["area", "sex", "genre"], 2)] +
[f"{extend.get('char', 'index')}.html"])
elif "id" in extend and extend["id"] not in ["index", "top"]:
url = tid.replace("index.html", f"{extend['id']}.html").replace("top.html", f"{extend['id']}.html")
if url == tid:
url = f"{tid.rsplit('/', 1)[0]}/{extend['id']}.html"
if pg > 1:
sep = "/" if any(x in url for x in ["/singerlist/", "/radiolist/", "/mvlist/", "/playtype/", "/list/"]) else "_"
url = re.sub(r'(_\d+|/\d+)?\.html$', f'{sep}{pg}.html', url)
doc = self.getpq(url)
items = doc(".play_list li, .video_list li, .pic_list li, .singer_list li, .ali li, .layui-row li, .base_l li")
return {
"list": self._parse_list(items, tid),
"page": pg,
"pagecount": 9999,
"limit": 90,
"total": 999999
}
def searchContent(self, key, quick, pg="1"):
doc = self.getpq(f"/so/{quote(key)}/{pg}.html")
items = doc(".base_l li, .play_list li")
return {
"list": self._parse_list(items, "search"),
"page": int(pg)
}
def detailContent(self, ids):
url = self._abs(ids[0])
doc = self.getpq(url)
vod = {
"vod_id": url,
"vod_name": self._clean(doc("h1").text() or doc("title").text()),
"vod_pic": self._abs(doc(".djpg img, .pic img, .djpic img").attr("src")),
"vod_play_from": "爱听音乐",
"vod_content": ""
}
if any(x in url for x in ["/playlist/", "/album/", "/list/", "/singer/", "/special/", "/radio/", "/radiolist/"]):
eps = self._get_eps(doc)
page_urls = {
self._abs(a.attr("href"))
for a in doc(".page a, .dede_pages a, .pagelist a").items()
if a.attr("href") and "javascript" not in a.attr("href")
} - {url}
if page_urls:
with ThreadPoolExecutor(max_workers=5) as ex:
futures = []
for u in sorted(page_urls, key=lambda x: int(re.search(r'[_/](\d+)\.html', x).group(1)) if re.search(
r'[_/](\d+)\.html', x) else 0):
futures.append(ex.submit(lambda uu: self._get_eps(self.getpq(uu)), u))
for f in as_completed(futures):
eps.extend(f.result() or [])
if eps:
vod.update({
"vod_play_from": "播放列表",
"vod_play_url": "#".join(eps)
})
return {"list": [vod]}
play_list = []
if mid := re.search(r'/(song|mp3|radio|radiolist|radioplay)/([^/]+)\.html', url):
lrc_url = f"{self.host}/plug/down.php?ac=music&lk=lrc&id={mid.group(2)}"
play_list = [f"播放${self.e64('0@@@@' + url + '|||' + lrc_url)}"]
elif vid := re.search(r'/(video|mp4)/([^/]+)\.html', url):
with ThreadPoolExecutor(max_workers=3) as ex:
fs = {
ex.submit(self._api, "/plug/down.php", {"ac": "vplay", "id": vid.group(2), "q": q}): n
for n, q in [("蓝光", 1080), ("超清", 720), ("高清", 480)]
}
play_list = [f"{fs[f]}${self.e64('0@@@@'+u)}" for f in as_completed(fs) if (u := f.result())]
play_list.sort(key=lambda x: {"": 0, "": 1, "": 2}.get(x[0], 3))
vod["vod_play_url"] = "#".join(play_list) if play_list else f"解析失败${self.e64('1@@@@'+url)}"
return {"list": [vod]}
def playerContent(self, flag, id, vipFlags):
raw = self.d64(id).split("@@@@")[-1]
url, subt = raw.split("|||") if "|||" in raw else (raw, "")
url = url.replace(r"\/", "/")
if ".html" in url and not self.isVideoFormat(url):
if mid := re.search(r'/(song|mp3|radio|radiolist|radioplay)/([^/]+)\.html', url):
if r_url := self._api("/js/play.php", method="POST", data={"id": mid.group(2), "type": "music"},
headers={"Referer": url.replace("http://", "https://"),
"X-Requested-With": "XMLHttpRequest"}):
url = r_url if ".php" not in r_url else url
elif vid := re.search(r'/(video|mp4)/([^/]+)\.html', url):
with ThreadPoolExecutor(max_workers=3) as ex:
for f in as_completed(
[ex.submit(self._api, "/plug/down.php", {"ac": "vplay", "id": vid.group(2), "q": q}) for q in
[1080, 720, 480]]):
if v_url := f.result():
url = v_url
break
result = {"parse": 0, "url": url, "header": {"User-Agent": self.headers["User-Agent"]}}
if "22a5.com" in url:
result["header"]["Referer"] = self.host + "/"
# OK影视3.6.5+支持LRC格式滚动歌词
if subt:
try:
r = self.session.get(subt, headers={"Referer": self.host + "/"}, timeout=5)
lrc_content = r.text
if lrc_content:
lrc_content = self._filter_lrc_ads(lrc_content)
result["lrc"] = lrc_content
except:
pass
return result
def _filter_lrc_ads(self, lrc_text):
"""过滤LRC歌词中的广告内容"""
lines = lrc_text.splitlines()
filtered_lines = []
# 广告关键词模式
ad_patterns = [
r'欢迎来访.*',
r'本站.*',
r'.*广告.*',
r'QQ群.*',
r'.*www\..*',
r'.*http.*',
r'.*\.com.*',
r'.*\.cn.*',
r'.*\.net.*',
r'.*音乐网.*',
r'.*提供.*',
r'.*下载.*',
]
for line in lines:
if re.match(r'\[\d{2}:\d{2}', line):
is_ad = False
for pattern in ad_patterns:
if re.search(pattern, line, re.IGNORECASE):
is_ad = True
break
if not is_ad:
filtered_lines.append(line)
else:
filtered_lines.append(line)
return '\n'.join(filtered_lines)
def localProxy(self, param):
url = unquote(param.get("url", ""))
type_ = param.get("type")
if type_ == "img":
try:
headers = {
"Referer": "https://www.baidu.com/",
"User-Agent": self.headers["User-Agent"],
"Accept": "image/webp,image/apng,image/*,*/*;q=0.8",
"Accept-Language": "zh-CN,zh;q=0.9"
}
resp = self.session.get(url, headers=headers, timeout=10)
return [200, "image/jpeg", resp.content, {}]
except Exception as e:
print(f"图片代理失败: {e}")
return [404, "text/plain", b"", {}]
elif type_ == "lrc":
try:
r = self.session.get(url, headers={"Referer": self.host + "/"}, timeout=5)
lrc_content = r.text
lrc_content = self._filter_lrc_ads(lrc_content)
return [200, "application/octet-stream", lrc_content.encode('utf-8'), {}]
except:
return [404, "text/plain", "Error", {}]
return None
# ==================== 辅助方法 ====================
def _parse_list(self, items, tid=""):
"""解析列表项,修复歌手头像 - 直接返回原始图片URL"""
res = []
for li in items.items():
a = li("a").eq(0)
if not (href := a.attr("href")) or href == "/" or any(x in href for x in ["/user/", "/login/", "javascript"]):
continue
if not (name := self._clean(li(".name").text() or a.attr("title") or a.text())):
continue
is_singer = "/singer/" in href or "/singerlist" in tid
pic = ""
src = ""
if is_singer:
img = li(".pic img").eq(0)
src = img.attr("src") or ""
if not src:
img = li("img").eq(0)
src = img.attr("src") or ""
else:
img = li("img").eq(0)
src = img.attr("src") or ""
if not src:
img = li(".pic img").eq(0)
src = img.attr("src") or ""
if src:
if src.startswith('//'):
src = 'https:' + src
elif src.startswith('/'):
src = self.host + src
pic = src
res.append({
"vod_id": self._abs(href),
"vod_name": name,
"vod_pic": pic,
"style": {
"type": "oval" if is_singer else ("list" if any(
x in tid for x in ["/list/", "/playtype/", "/albumlist/"]) else "rect"),
"ratio": 1 if is_singer else 1.33
}
})
return res
def _get_eps(self, doc):
eps = []
for li in doc(".play_list li, .song_list li, .music_list li").items():
a = li("a").eq(0)
href = a.attr("href")
if not href or not re.search(r'/(song|mp3|radio|radiolist|radioplay)/([^/]+)\.html', href):
continue
full_url = self._abs(href)
lrc_part = ""
mid = re.search(r'/(song|mp3|radio|radiolist|radioplay)/([^/]+)\.html', full_url)
if mid:
lrc_url = f"{self.host}/plug/down.php?ac=music&lk=lrc&id={mid.group(2)}"
lrc_part = f"|||{lrc_url}"
eps.append(f"{self._clean(a.text() or li('.name').text())}${self.e64('0@@@@' + full_url + lrc_part)}")
return eps
def _clean(self, text):
return re.sub(
r'(爱玩音乐网|视频下载说明|视频下载地址|www\.2t58\.com|MP3免费下载|LRC歌词下载|全部歌曲|\[第\d+页\]|刷新|每日推荐|最新|热门|推荐|MV|高清|无损)',
'',
text or '',
flags=re.I
).strip()
def _fetch_filters(self, url):
doc = self.getpq(url)
filters = []
for i, group in enumerate([
doc(".ilingku_fl"),
doc(".class_list"),
doc(".screen_list"),
doc(".box_list"),
doc(".nav_list")
]):
if group:
opts = [{"n": "全部", "v": "top" if "top" in url else "index"}]
seen = set()
for a in group("a").items():
v = (a.attr("href") or "").split("?")[0].rstrip('/').split('/')[-1].replace('.html', '')
if v and v not in seen:
opts.append({"n": a.text().strip(), "v": v})
seen.add(v)
if len(opts) > 1:
filters.append({"key": f"id{i}" if i else "id", "name": "分类", "value": opts})
return filters
def _api(self, path, params=None, method="GET", headers=None, data=None):
try:
h = self.headers.copy()
if headers:
h.update(headers)
r = (self.session.post if method == "POST" else self.session.get)(
f"{self.host}{path}",
params=params,
data=data,
headers=h,
timeout=10,
allow_redirects=False
)
if loc := r.headers.get("Location"):
return self._abs(loc.strip())
return self._abs(r.json().get("url", "").replace(r"\/", "/")) or (r.text.strip() if r.text.strip().startswith(
"http") else "")
except:
return ""
def _abs(self, url):
if not url:
return ""
if url.startswith("http"):
return url
if url.startswith("//"):
return "https:" + url
return f"{self.host}{'/' if not url.startswith('/') else ''}{url}"
def e64(self, text):
return b64encode(text.encode("utf-8")).decode("utf-8")
def d64(self, text):
return b64decode(text.encode("utf-8")).decode("utf-8")