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