// ==UserScript==
// @name 🎬 主流网站视频解析观看助手 - 完整功能版
// @namespace https://github.com/video-helper
// @version 1.2.2
// @description 完整功能,自动解析,支持内嵌/弹窗播放,解决播放器定位问题
// @author 智能解析助手
// @match *://*.iqiyi.com/*
// @match *://v.qq.com/*
// @match *://*.youku.com/*
// @match *://*.mgtv.com/*
// @match *://*.bilibili.com/*
// @match *://*.le.com/*
// @match *://*.sohu.com/*
// @match *://*.pptv.com/*
// @match *://*.1905.com/*
// @match *://*.iq.com/*
// @grant GM_registerMenuCommand
// @grant GM_addStyle
// @grant GM_notification
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_openInTab
// @require https://cdn.jsdelivr.net/npm/sweetalert2@11
// @run-at document-end
// @icon https://cdn.jsdelivr.net/npm/simple-icons@v8/icons/vlc.svg
// @license MIT
// ==/UserScript==
(function() {
'use strict';
console.log('🎬 视频解析助手完整版:脚本加载');
// ==================== 核心配置 ====================
const CONFIG = {
vipBoxId: 'vip_jx_box_' + Math.ceil(Math.random() * 100000000),
autoPlayerKey: "auto_player_key",
autoPlayerVal: "auto_player_value",
currentApiKey: "current_api_index",
customApisKey: "custom_parse_apis"
};
// 解析接口配置 - 与原版完全一致
const parseApis = [
{name: "七哥", type: "1,3", url: "https://jx.nnxv.cn/tv.php?url=", recommended: true},
{name: "虾米", type: "1,3", url: "https://jx.xmflv.cc/?url=", recommended: true},
{name: "纯净1", type: "1,2,3", url: "https://im1907.top/?jx="},
{name: "B站1", type: "1,3", url: "https://jx.jsonplayer.com/player/?url="},
{name: "爱豆", type: "1,3", url: "https://jx.aidouer.net/?url="},
{name: "BL", type: "1,3", url: "https://vip.bljiex.com/?v="},
{name: "冰豆", type: "1,3", url: "https://api.qianqi.net/vip/?url="},
{name: "百域", type: "1,3", url: "https://jx.618g.com/?url="},
{name: "CK", type: "1,3", url: "https://www.ckplayer.vip/jiexi/?url="},
{name: "CHok", type: "1,3", url: "https://www.gai4.com/?url="},
{name: "ckmov", type: "1,3", url: "https://www.ckmov.vip/api.php?url="},
{name: "H8", type: "1,3", url: "https://www.h8jx.com/jiexi.php?url="},
{name: "JY", type: "1,3", url: "https://jx.playerjy.com/?url="},
{name: "解析", type: "1,3", url: "https://ckmov.ccyjjd.com/ckmov/?url="},
{name: "解析la", type: "1,3", url: "https://api.jiexi.la/?url="},
{name: "老板", type: "1,3", url: "https://vip.laobandq.com/jiexi.php?url="},
{name: "MAO", type: "1,3", url: "https://www.mtosz.com/m3u8.php?url="},
{name: "M3U8", type: "1,3", url: "https://jx.m3u8.tv/jiexi/?url="},
{name: "诺讯", type: "1,3", url: "https://www.nxflv.com/?url="},
{name: "OK", type: "1,3", url: "https://okjx.cc/?url="},
{name: "PM", type: "1,3", url: "https://www.playm3u8.cn/jiexi.php?url="},
{name: "盘古", type: "1,3", url: "https://www.pangujiexi.cc/jiexi.php?url="},
{name: "RDHK", type: "1,3", url: "https://jx.rdhk.net/?v="},
{name: "人人迷", type: "1,3", url: "https://jx.blbo.cc:4433/?url="},
{name: "思云", type: "1,3", url: "https://jx.ap2p.cn/?url="},
{name: "思古3", type: "1,3", url: "https://jsap.attakids.com/?url="},
{name: "听乐", type: "1,3", url: "https://jx.dj6u.com/?url="},
{name: "维多", type: "1,3", url: "https://jx.ivito.cn/?url="},
{name: "YT", type: "1,3", url: "https://jx.yangtu.top/?url="},
{name: "云端", type: "1,3", url: "https://sb.5gseo.net/?url="},
{name: "0523", type: "1,3", url: "https://go.yh0523.cn/y.cy?url="},
{name: "17云", type: "1,3", url: "https://www.1717yun.com/jx/ty.php?url="},
{name: "180", type: "1,3", url: "https://jx.000180.top/jx/?url="},
{name: "4K", type: "1,3", url: "https://jx.4kdv.com/?url="},
{name: "8090", type: "1,3", url: "https://www.8090g.cn/?url="},
{name: "剖元", type: "1,3", url: "https://www.pouyun.com/?url="},
{name: "全民", type: "1,3", url: "https://43.240.74.102:4433?url="},
{name: "夜幕", type: "1,3", url: "https://www.yemu.xyz/?url="},
{name: "M3U8TV", type: "1,3", url: "https://jx.m3u8.tv/jiexi/?url="},
{name: "playm3u8", type: "1,3", url: "https://www.playm3u8.cn/jiexi.php?url="},
{name: "综合", type: "1,3", url: "https://jx.jsonplayer.com/player/?url="},
{name: "im1907", type: "2", url: "https://im1907.top/?jx="},
{name: "云析(带选集)", type: "2", url: "https://jx.yparse.com/index.php?url="},
];
// 去重处理
const uniqueApis = [];
const seenUrls = new Set();
parseApis.forEach(api => {
if (!seenUrls.has(api.url)) {
seenUrls.add(api.url);
uniqueApis.push(api);
}
});
// 合并自定义接口
const customApis = GM_getValue(CONFIG.customApisKey, []);
const allApis = [...uniqueApis, ...customApis];
// ==================== 样式注入 ====================
GM_addStyle(`
#${CONFIG.vipBoxId} {
cursor: pointer;
position: fixed;
top: 120px;
left: 0px;
z-index: 9999999;
text-align: left;
transition: left 0.3s ease;
}
#${CONFIG.vipBoxId} .img_box {
width: 32px;
height: 32px;
line-height: 32px;
text-align: center;
background-color: lightgreen;
margin: 10px 0px;
color: white;
font-size: 16px;
font-weight: bold;
border-radius: 5px;
}
#${CONFIG.vipBoxId} .vip_list {
display: none;
position: absolute;
border-radius: 5px;
left: 32px;
top: 0;
background-color: #3f4149;
border: 1px solid white;
padding: 10px 0px;
width: 380px;
max-height: 400px;
overflow-y: auto;
}
#${CONFIG.vipBoxId} .vip_list.visible {
display: block;
}
#${CONFIG.vipBoxId} .vip_list ul {
padding-left: 10px;
}
#${CONFIG.vipBoxId} .vip_list li {
border-radius: 2px;
font-size: 12px;
color: #DCDCDC;
text-align: center;
width: calc(25% - 14px);
line-height: 21px;
float: left;
border: 1px solid gray;
padding: 0 4px;
margin: 4px 2px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
cursor: pointer;
}
#${CONFIG.vipBoxId} .vip_list li:hover {
color: #1c84c6;
border: 1px solid #1c84c6;
}
#${CONFIG.vipBoxId} li.selected {
color: #1c84c6;
border: 1px solid #1c84c6;
}
#${CONFIG.vipBoxId} #vip_auto {
background-color: #ff69b4;
}
.mode-toggle {
color: #1c84c6;
cursor: pointer;
margin-left: 2px;
}
.section-title {
color: #1c84c6;
font-weight: bold;
font-size: 14px;
padding: 5px 0px;
clear: both;
}
.complex-api-list li {
width: calc(50% - 14px);
}
`);
// ==================== 工具函数 ====================
// 查找目标元素(与原版类似,但更简单)
function waitForElement(selector, timeout = 5000) {
return new Promise((resolve, reject) => {
if (document.querySelector(selector)) {
return resolve(document.querySelector(selector));
}
const observer = new MutationObserver(() => {
if (document.querySelector(selector)) {
observer.disconnect();
resolve(document.querySelector(selector));
}
});
observer.observe(document.body, { childList: true, subtree: true });
setTimeout(() => {
observer.disconnect();
reject(new Error(`未找到元素: ${selector}`));
}, timeout);
});
}
// 增强的播放器查找函数(解决“无法确定视频播放位置”问题)
function findVideoPlayer() {
console.log('🔍 开始查找视频播放器...');
// 平台专用选择器
const platformSelectors = [
// 爱奇艺
'#player, .qiyi-player, [data-player]',
// 腾讯视频
'#tenvideo_video_player, .txp_player, .player_container',
// 优酷
'.yk-player, #player, [id*="player"]',
// 芒果TV
'#mgtv-player-wrap, .mgtv-player',
// 哔哩哔哩
'#bilibiliPlayer, .bpx-player-container',
// 通用选择器
'video, .player, .video-player, .player-container, .video-container, iframe[src*="video"]',
'div[class*="player"], div[class*="video"]',
'#player, #video-player, #flashbox'
];
for (let selector of platformSelectors) {
const elements = document.querySelectorAll(selector);
if (elements.length > 0) {
console.log(`✅ 找到播放器元素,选择器: ${selector}, 数量: ${elements.length}`);
// 返回最大的或最可见的那个
let largestElement = elements[0];
let largestArea = 0;
for (let elem of elements) {
const rect = elem.getBoundingClientRect();
const area = rect.width * rect.height;
if (area > largestArea && area > 10000) { // 面积大于10000px²
largestArea = area;
largestElement = elem;
}
}
return largestElement;
}
}
console.log('❌ 未找到标准播放器元素,尝试备用方案...');
// 备用方案:查找包含"播放"文字的容器
const playTextElements = document.querySelectorAll('div, section, article');
for (let elem of playTextElements) {
if (elem.textContent.includes('播放') ||
elem.textContent.includes('player') ||
elem.textContent.includes('Player')) {
const rect = elem.getBoundingClientRect();
if (rect.width > 300 && rect.height > 200) {
console.log('✅ 通过文本找到可能的播放器容器');
return elem;
}
}
}
return null;
}
// 显示消息
function showAlert(title, text, icon = 'info') {
if (typeof Swal !== 'undefined') {
Swal.fire({ title, text, icon, toast: true, position: 'top-end', timer: 3000 });
} else {
alert(`${title}: ${text}`);
}
}
// ==================== 主功能函数 ====================
// 创建VIP按钮和面板(与原版布局一致)
function createVipButton() {
if (document.getElementById(CONFIG.vipBoxId)) return;
console.log('🛠️ 创建VIP按钮界面');
// 分离接口
let simpleApisHtml = "
[内嵌播放+弹窗无选集]
";
let complexApisHtml = "[弹窗带选集]
";
allApis.forEach((item, index) => {
const types = item.type.split(',');
const name = item.name;
if (types.includes("1") || types.includes("3")) {
if ((types.includes("1") || types.includes("3")) && !types.includes("2")) {
if (types.includes("1") && types.includes("3")) {
simpleApisHtml += `- ${name} | 内嵌
`;
} else if (types.includes("1")) {
simpleApisHtml += `- ${name} | 内嵌
`;
} else if (types.includes("3")) {
simpleApisHtml += `- ${name} | 弹窗
`;
}
}
if (types.includes("1") && types.includes("2") && types.includes("3")) {
simpleApisHtml += `- ${name} | 内嵌
`;
}
}
if (types.includes("2")) {
complexApisHtml += `- ${name}
`;
}
});
simpleApisHtml += "
";
complexApisHtml += "
";
let autoPlay = GM_getValue(CONFIG.autoPlayerKey) ? "开" : "关";
const vipBox = document.createElement('div');
vipBox.id = CONFIG.vipBoxId;
vipBox.innerHTML = `
VIP
${simpleApisHtml}
${complexApisHtml}
${autoPlay}
`;
document.body.appendChild(vipBox);
bindEvents();
// 检查自动播放
if (GM_getValue(CONFIG.autoPlayerKey)) {
console.log('⏱️ 自动解析已开启,准备执行...');
setTimeout(autoPlayVideo, 2500);
}
}
// 绑定事件
function bindEvents() {
const vipBox = document.getElementById(CONFIG.vipBoxId);
if (!vipBox) return;
const vipIcon = vipBox.querySelector('.vip_icon');
const vipList = vipBox.querySelector('.vip_list');
// 鼠标悬停显示/隐藏面板
vipIcon.addEventListener('mouseenter', () => {
vipList.classList.add('visible');
});
vipIcon.addEventListener('mouseleave', (e) => {
if (!vipList.contains(e.relatedTarget) && !vipIcon.contains(e.relatedTarget)) {
vipList.classList.remove('visible');
}
});
vipList.addEventListener('mouseleave', (e) => {
if (!vipIcon.contains(e.relatedTarget) && !vipList.contains(e.relatedTarget)) {
vipList.classList.remove('visible');
}
});
// 点击接口事件
vipBox.querySelectorAll('.api-item').forEach(item => {
item.addEventListener('click', (e) => {
if (e.target.classList.contains('mode-toggle')) {
togglePlayMode(e.target);
return;
}
const index = parseInt(item.getAttribute('data-index'));
const api = allApis[index];
// 获取播放模式
let playMode;
if (item.classList.contains('combined-simple')) {
playMode = item.getAttribute('data-current-mode');
} else {
playMode = item.getAttribute('data-mode');
}
// 保存当前选择的接口
GM_setValue(CONFIG.currentApiKey, index);
// 执行解析
if (playMode === "1") {
// 内嵌播放
playVideo(api, true);
// 更新选中状态
vipBox.querySelectorAll('.api-item').forEach(li => {
li.classList.remove('selected');
});
item.classList.add('selected');
} else {
// 弹窗播放
const url = api.url + encodeURIComponent(window.location.href);
GM_openInTab(url, {active: true, insert: true});
showAlert('正在打开', `使用 ${api.name} 解析`);
}
});
});
// 自动解析开关
const autoBtn = vipBox.querySelector('#vip_auto');
autoBtn.addEventListener('click', function() {
const isOn = GM_getValue(CONFIG.autoPlayerKey);
GM_setValue(CONFIG.autoPlayerKey, !isOn);
this.textContent = !isOn ? '开' : '关';
this.title = !isOn ? '自动解析已开启' : '自动解析已关闭';
showAlert('设置已保存', `自动解析已${!isOn ? '开启' : '关闭'}`);
if (!isOn) {
setTimeout(autoPlayVideo, 1000);
}
});
// 添加自定义接口按钮
const addApiBtn = vipBox.querySelector('#add_api_btn');
addApiBtn.addEventListener('click', function() {
showCustomApiForm();
});
// 拖拽功能
enableDragging(vipBox);
}
// 切换播放模式
function togglePlayMode(element) {
const item = element.closest('.api-item');
const modes = item.getAttribute('data-modes').split(',');
const currentMode = item.getAttribute('data-current-mode');
let nextIndex = modes.indexOf(currentMode) + 1;
if (nextIndex >= modes.length) nextIndex = 0;
const nextMode = modes[nextIndex];
element.textContent = nextMode === '1' ? '内嵌' : '弹窗';
item.setAttribute('data-current-mode', nextMode);
}
// 播放视频(内嵌模式)
function playVideo(api, isEmbed) {
if (!isEmbed) return;
console.log(`▶️ 尝试内嵌播放,使用接口: ${api.name}`);
const playerContainer = findVideoPlayer();
if (!playerContainer) {
console.log('❌ 未找到视频播放器容器');
showAlert('播放器未找到', '无法定位视频播放区域,请确保已在视频播放页面。', 'warning');
return;
}
console.log('✅ 找到播放器容器,准备替换:', playerContainer);
// 保存原始内容(以便恢复)
if (!playerContainer._originalHTML) {
playerContainer._originalHTML = playerContainer.innerHTML;
}
// 清空容器
playerContainer.innerHTML = '';
// 创建iframe
const iframe = document.createElement('iframe');
iframe.src = api.url + encodeURIComponent(window.location.href);
iframe.style.width = '100%';
iframe.style.height = '100%';
iframe.style.border = 'none';
iframe.allowFullscreen = true;
iframe.setAttribute('allow', 'autoplay; fullscreen');
// 容器样式
playerContainer.style.position = 'relative';
playerContainer.style.width = '100%';
playerContainer.style.minHeight = '500px';
playerContainer.style.zIndex = '99999';
playerContainer.style.backgroundColor = '#000';
playerContainer.appendChild(iframe);
console.log('✅ 内嵌播放器已加载');
showAlert('解析成功', `正在使用 ${api.name} 播放`, 'success');
}
// 自动播放视频
function autoPlayVideo() {
if (!GM_getValue(CONFIG.autoPlayerKey)) return;
const savedIndex = GM_getValue(CONFIG.currentApiKey, 0);
if (savedIndex >= 0 && savedIndex < allApis.length) {
const api = allApis[savedIndex];
console.log(`🤖 自动播放: 使用上次选择的接口 ${api.name}`);
// 只对内嵌播放接口启用自动播放
if (api.type.includes('1')) {
playVideo(api, true);
// 更新UI选中状态
const vipBox = document.getElementById(CONFIG.vipBoxId);
if (vipBox) {
const items = vipBox.querySelectorAll('.api-item');
if (items[savedIndex]) {
items.forEach(item => item.classList.remove('selected'));
items[savedIndex].classList.add('selected');
}
}
}
}
}
// 显示自定义接口表单
function showCustomApiForm() {
if (typeof Swal === 'undefined') {
alert('请先刷新页面加载SweetAlert2库');
return;
}
Swal.fire({
title: '添加自定义解析接口',
html: `
`,
focusConfirm: false,
showCancelButton: true,
confirmButtonText: '添加',
cancelButtonText: '取消',
preConfirm: () => {
const name = document.getElementById('api-name').value.trim();
const url = document.getElementById('api-url').value.trim();
const type = document.getElementById('api-type').value;
if (!name || !url) {
Swal.showValidationMessage('请填写完整信息');
return false;
}
if (!url.includes('?url=') && !url.includes('&url=')) {
Swal.showValidationMessage('接口地址必须包含 ?url= 或 &url= 参数');
return false;
}
return { name, url, type };
}
}).then(result => {
if (result.isConfirmed) {
const newApi = {
name: result.value.name,
type: result.value.type,
url: result.value.url
};
const customApis = GM_getValue(CONFIG.customApisKey, []);
customApis.push(newApi);
GM_setValue(CONFIG.customApisKey, customApis);
showAlert('添加成功', '自定义接口已保存,请刷新页面后生效', 'success');
}
});
}
// 启用拖拽
function enableDragging(container) {
let isDragging = false;
let startX, startY, startLeft, startTop;
container.addEventListener('mousedown', function(e) {
if (!e.target.closest('.img_box')) return;
isDragging = true;
startX = e.clientX;
startY = e.clientY;
const rect = container.getBoundingClientRect();
startLeft = rect.left;
startTop = rect.top;
document.addEventListener('mousemove', drag);
document.addEventListener('mouseup', stopDrag);
e.preventDefault();
});
function drag(e) {
if (!isDragging) return;
const deltaX = e.clientX - startX;
const deltaY = e.clientY - startY;
let newLeft = startLeft + deltaX;
let newTop = startTop + deltaY;
newLeft = Math.max(0, Math.min(newLeft, window.innerWidth - 50));
newTop = Math.max(0, Math.min(newTop, window.innerHeight - 100));
container.style.left = newLeft + 'px';
container.style.top = newTop + 'px';
}
function stopDrag() {
isDragging = false;
document.removeEventListener('mousemove', drag);
document.removeEventListener('mouseup', stopDrag);
}
}
// 注册菜单命令
function registerMenuCommands() {
try {
GM_registerMenuCommand('🎬 显示解析面板', () => {
const vipBox = document.getElementById(CONFIG.vipBoxId);
if (vipBox) {
vipBox.querySelector('.vip_list').classList.add('visible');
}
});
GM_registerMenuCommand('⚙️ 工具状态', () => {
const autoStatus = GM_getValue(CONFIG.autoPlayerKey) ? '开启' : '关闭';
const apiCount = allApis.length;
showAlert('脚本状态', `接口数量: ${apiCount}\n自动解析: ${autoStatus}`, 'info');
});
GM_registerMenuCommand('🔧 添加自定义接口', () => {
showCustomApiForm();
});
} catch (e) {
console.log('菜单注册失败:', e);
}
}
// ==================== 初始化 ====================
function init() {
console.log('🚀 视频解析助手初始化...');
// 检查是否在支持的网站
const host = window.location.hostname;
const isVideoSite = [
'iqiyi.com', 'v.qq.com', 'youku.com', 'mgtv.com',
'bilibili.com', 'le.com', 'sohu.com', 'pptv.com', '1905.com', 'iq.com'
].some(site => host.includes(site));
if (!isVideoSite) {
console.log('🌐 当前网站不支持,跳过初始化');
return;
}
console.log('✅ 当前网站支持,创建界面...');
// 创建界面
createVipButton();
// 注册菜单
registerMenuCommands();
console.log('🎉 视频解析助手初始化完成');
}
// 启动
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();