// ==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 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(); } })();