上传文件至「js」
This commit is contained in:
@@ -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
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user