上传文件至「js」

This commit is contained in:
2026-08-05 04:12:06 +02:00
parent b84bdfc185
commit 451386e76e
+83 -63
View File
@@ -41,41 +41,38 @@ function fixUrl(url) {
return API_HOST + '/' + url;
}
// ============ 解析视频列表 ============
// ============ 解析视频列表(基于实际HTML结构) ============
function parseVideoList(html) {
const videos = [];
if (!html) return videos;
// 使用正则匹配 stui-vodlist__box 或 stui-vodlist__item
const itemPattern = /<div[^>]*class="[^"]*stui-vodlist__box[^"]*"[^>]*>([\s\S]*?)<\/div>\s*<\/div>\s*<\/div>/g;
// 匹配每个 li 中的 stui-vodlist__box
const boxPattern = /<div[^>]*class="stui-vodlist__box"[^>]*>([\s\S]*?)<\/div>\s*<\/div>\s*<\/div>/g;
let match;
while ((match = itemPattern.exec(html)) !== null) {
const block = match[1];
while ((match = boxPattern.exec(html)) !== null) {
try {
// 提取链接和标题
const linkMatch = block.match(/<a[^>]*class="[^"]*stui-vodlist__thumb[^"]*"[^>]*title="([^"]*)"[^>]*href="([^"]*)"[^>]*>/);
if (!linkMatch) continue;
const title = linkMatch[1].trim();
let href = linkMatch[2];
const block = match[1];
// 提取 a 标签 - 包含 href, title, data-original
const aMatch = block.match(/<a[^>]*class="[^"]*stui-vodlist__thumb[^"]*"[^>]*href="([^"]+)"[^>]*title="([^"]*)"[^>]*(?:data-original|src)="([^"]+)"[^>]*>/);
if (!aMatch) continue;
let href = aMatch[1];
const title = aMatch[2].trim();
let pic = aMatch[3];
if (!title || !href) continue;
// 提取图片
let pic = '';
const picMatch = block.match(/data-original="([^"]+)"/);
if (picMatch) {
pic = picMatch[1];
} else {
const srcMatch = block.match(/src="([^"]+)"/);
if (srcMatch) pic = srcMatch[1];
// 提取备注 (pic-text)
let remark = '更新中';
const remarkMatch = block.match(/<span[^>]*class="pic-text[^"]*"[^>]*>([^<]*)<\/span>/);
if (remarkMatch) {
remark = remarkMatch[1].trim();
}
// 提取备注
let remark = '';
const remarkMatch = block.match(/<span[^>]*class="pic-text[^"]*"[^>]*>([^<]*)<\/span>/);
if (remarkMatch) remark = remarkMatch[1].trim();
// 修复 URL
if (pic && !pic.startsWith('http')) pic = fixUrl(pic);
if (href && !href.startsWith('http')) href = fixUrl(href);
@@ -88,14 +85,14 @@ function parseVideoList(html) {
} catch (e) {}
}
// 备用解析方式
// 备用解析:如果没有匹配到,尝试用更简单的方式
if (videos.length === 0) {
const pattern = /<a[^>]*class="[^"]*stui-vodlist__thumb[^"]*"[^>]*title="([^"]*)"[^>]*(?:data-original|src)="([^"]*)"[^>]*href="([^"]*)"[^>]*>/g;
let m;
while ((m = pattern.exec(html)) !== null) {
const title = m[1].trim();
let pic = m[2];
let href = m[3];
const altPattern = /<a[^>]*class="[^"]*stui-vodlist__thumb[^"]*"[^>]*href="([^"]+)"[^>]*title="([^"]*)"[^>]*(?:data-original|src)="([^"]+)"[^>]*>/g;
let altMatch;
while ((altMatch = altPattern.exec(html)) !== null) {
let href = altMatch[1];
const title = altMatch[2].trim();
let pic = altMatch[3];
if (!title || !href) continue;
if (pic && !pic.startsWith('http')) pic = fixUrl(pic);
if (href && !href.startsWith('http')) href = fixUrl(href);
@@ -124,18 +121,15 @@ const FILTERS = {
'1': [
{ key: 'class', name: '类型', value: [
{ v: '1', n: '全部' },
{ v: '6', n: '动作片' },
{ v: '7', n: '喜剧片' },
{ v: '8', n: '爱情片' },
{ v: '9', n: '科幻片' },
{ v: '10', n: '恐怖片' },
{ v: '11', n: '剧情片' },
{ v: '12', n: '战争片' },
{ v: '13', n: '记录片' },
{ v: '14', n: '悬疑片' },
{ v: '15', n: '犯罪片' },
{ v: '16', n: '奇幻片' },
{ v: '31', n: '动画片' }
{ v: 'dongzuopian', n: '动作片' },
{ v: 'xijupian', n: '喜剧片' },
{ v: 'aiqingpian', n: '爱情片' },
{ v: 'kehuanpian', n: '科幻片' },
{ v: 'kongbupian', n: '恐怖片' },
{ v: 'juqingpian', n: '剧情片' },
{ v: 'zhanzhengpian', n: '战争片' },
{ v: 'jilupian', n: '记录片' },
{ v: 'donghuapian', n: '动画片' }
]},
{ key: 'area', name: '地区', value: [
{ v: '0', n: '全部' },
@@ -145,9 +139,6 @@ const FILTERS = {
{ v: '美国', n: '美国' },
{ v: '日本', n: '日本' },
{ v: '韩国', n: '韩国' },
{ v: '英国', n: '英国' },
{ v: '法国', n: '法国' },
{ v: '德国', n: '德国' },
{ v: '泰国', n: '泰国' },
{ v: '印度', n: '印度' },
{ v: '加拿大', n: '加拿大' },
@@ -179,11 +170,11 @@ const FILTERS = {
'2': [
{ key: 'class', name: '类型', value: [
{ v: '2', n: '全部' },
{ v: '17', n: '国产剧' },
{ v: '21', n: '欧美剧' },
{ v: '20', n: '日韩剧' },
{ v: '18', n: '港台剧' },
{ v: '22', n: '海外剧' }
{ v: 'guochanju', n: '国产剧' },
{ v: 'oumeiju', n: '欧美剧' },
{ v: 'rihanju', n: '日韩剧' },
{ v: 'gangtaiju', n: '港台剧' },
{ v: 'haiwaiju', n: '海外剧' }
]},
{ key: 'area', name: '地区', value: [
{ v: '0', n: '全部' },
@@ -277,22 +268,49 @@ async function category(tid, pg, filter, extend) {
const classVal = (extend && extend.class) || '';
const areaVal = (extend && extend.area) || '0';
const yearVal = (extend && extend.year) || '0';
// sort 仅用于排序,URL中不体现
const sortVal = (extend && extend.sort) || 'time';
// 构建URL: /movie/fenlei{tid}--{class}--{area}--{year}---{page}---.html
let c = (classVal && classVal !== '1' && classVal !== '2') ? classVal : '';
let a = (areaVal !== '0') ? areaVal : '';
let y = (yearVal !== '0') ? yearVal : '';
// 构建筛选URL
let url = `${API_HOST}/vodshow`;
let url;
if (c || a || y) {
url = `${API_HOST}/movie/fenlei${tid}--${c}--${a}--${y}---${page}---.html`;
// 构建参数
const params = [];
if (classVal && classVal !== '1' && classVal !== '2') {
params.push(`id/${classVal}`);
}
if (areaVal && areaVal !== '0') {
params.push(`area/${encodeURIComponent(areaVal)}`);
}
if (yearVal && yearVal !== '0') {
params.push(`year/${yearVal}`);
}
if (sortVal && sortVal !== 'time') {
params.push(`by/${sortVal}`);
}
// 如果没有任何筛选,使用默认分类页
if (params.length === 0) {
if (tid === '1') {
url = `${API_HOST}/movie/fenlei1---${page}.html`;
} else if (tid === '2') {
url = `${API_HOST}/movie/fenlei2---${page}.html`;
} else if (tid === '3') {
url = `${API_HOST}/movie/fenlei3---${page}.html`;
} else if (tid === '4') {
url = `${API_HOST}/movie/fenlei4---${page}.html`;
} else {
url = `${API_HOST}/vodshow/id/${tid}/page/${page}.html`;
}
} else {
url = `${API_HOST}/movie/fenlei${tid}---${page}.html`;
// 有筛选条件:/vodshow/id/dongzuopian/area/大陆/year/2024/by/time/page/2.html
const idParam = classVal && classVal !== '1' && classVal !== '2' ? `id/${classVal}` : `id/${tid}`;
const allParams = [idParam, ...params];
url = `${API_HOST}/vodshow/${allParams.join('/')}/page/${page}.html`;
}
const html = await fetchHtml(url);
const videos = parseVideoList(html);
return JSON.stringify({
list: videos,
page: page,
@@ -477,7 +495,6 @@ async function play(flag, id, flags) {
try {
const html = await fetchHtml(playUrl);
// 提取真实视频地址
let realUrl = null;
// 匹配 JSON 中的 url
@@ -495,13 +512,16 @@ async function play(flag, id, flags) {
}
}
// 直接匹配 m3u8 URL
if (!realUrl) {
const m3u8Match = html.match(/https?:\/\/[^"'\s<>]+\.m3u8[^"'\s<>]*/i);
if (m3u8Match) realUrl = m3u8Match[0];
}
// 匹配 iframe 并递归
if (!realUrl) {
const mp4Match = html.match(/https?:\/\/[^"'\s<>]+\.mp4[^"'\s<>]*/i);
if (mp4Match) realUrl = mp4Match[0];
}
if (!realUrl) {
const iframeMatch = html.match(/<iframe[^>]*src=["']([^"']+)["']/i);
if (iframeMatch) {
@@ -536,8 +556,8 @@ export function __jsEvalReturn() {
home: home,
homeVod: homeVod,
category: category,
detail: detail,
search: search,
detail: detail,
play: play
};
}