全网VIP视频

全网VIP视频免费,智能选择有效解析链接,支持手动切换解析源

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name              全网VIP视频
// @namespace        
// @version           2025.9.29
// @description       全网VIP视频免费,智能选择有效解析链接,支持手动切换解析源
// @icon              https://nuaa.tech/zz.svg
// @author            https://pro.gleeze.com/article/46
// @include           *://v.qq.com/*
// @include           *://v.qq.com/x/cover/*
// @include           *://v.qq.com/tv/*
// @include           *://*.iqiyi.com/*
// @include           *://*.iqiyi.com/a_*
// @include           *://*.iqiyi.com/w_*
// @include           *://*.iq.com/play/*
// @include           *://*.youku.com/*
// @include           *://*.youku.com/video*
// @include           *://*.youku.com/*?vid=*
// @include           *://*.mgtv.com/b/*
// @include           *://*.tudou.com/*
// @include           *://*.tudou.com/programs/view/*
// @include           *://*.tudou.com/albumplay/*
// @include           *://film.sohu.com/album/*
// @include           *://tv.sohu.com/*
// @include           *://*.bilibili.com/*
// @include           *://*.bilibili.com/bangumi/play/*
// @include           *://v.pptv.com/show/*
// @include           *://vip.pptv.com/show/*
// @include           *://www.wasu.cn/Play/show/*
// @include           *://*.le.com/ptv/vplay/*
// @include           *://*.acfun.cn/v/*
// @include           *://*.acfun.cn/bangumi/*
// @include           *://*.1905.com/play/*
// @include           *://m.v.qq.com/x/page/*
// @include           *://m.v.qq.com/x/cover/*
// @include           *://m.v.qq.com/*
// @include           *://m.iqiyi.com/*
// @include           *://m.iqiyi.com/kszt/*
// @include           *://m.youku.com/video/*
// @include           *://m.mgtv.com/b/*
// @include           *://m.tv.sohu.com/v/*
// @include           *://m.film.sohu.com/album/*
// @include           *://m.pptv.com/show/*
// @include           *://m.bilibili.com/anime/*
// @include           *://m.bilibili.com/video/*
// @include           *://m.bilibili.com/bangumi/play/*
// @connect           api.bilibili.com
// @grant             unsafeWindow
// @grant             GM_addStyle
// @grant             GM_openInTab
// @grant             GM_getValue
// @grant             GM_setValue
// @grant             GM_xmlhttpRequest
// @grant             GM_notification
// @charset		      UTF-8
// @license           GPL License
// ==/UserScript==

const util = (function () {

    function findTargetElement(targetContainer) {
        const body = window.document;
        let tabContainer;
        let tryTime = 0;
        const maxTryTime = 120;
        return new Promise((resolve, reject) => {
            let interval = setInterval(() => {
                tabContainer = body.querySelector(targetContainer);
                if (tabContainer) {
                    clearInterval(interval);
                    resolve(tabContainer);
                }
                if ((++tryTime) === maxTryTime) {
                    clearInterval(interval);
                    reject();
                }
            }, 500);
        });
    }

    function urlChangeReload() {
        const oldHref = window.location.href;
        let interval = setInterval(() => {
            let newHref = window.location.href;
            if (oldHref !== newHref) {
                clearInterval(interval);
                window.location.reload();
            }
        }, 500);
    }

    function reomveVideo() {
        setInterval(() => {
            for (let video of document.getElementsByTagName("video")) {
                if (video.src) {
                    video.removeAttribute("src");
                    video.muted = true;
                    video.load();
                    video.pause();
                }
            }
        }, 500);
    }

    function syncRequest(option) {
        return new Promise((resolve, reject) => {
            option.onload = (res) => {
                resolve(res);
            };
            option.onerror = (err) => {
                reject(err);
            };
            GM_xmlhttpRequest(option);
        });
    }

    return {
        req: (option) => syncRequest(option),
        findTargetEle: (targetEle) => findTargetElement(targetEle),
        urlChangeReload: () => urlChangeReload(),
        reomveVideo: () => reomveVideo()
    }
})();


const superVip = (function () {

    const _CONFIG_ = {
        isMobile: navigator.userAgent.match(/(Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini)/i),
        currentPlayerNode: null,
        statusBoxId: 'vip_status_box' + Math.ceil(Math.random() * 100000000),
        switchBtnId: 'vip_switch_btn' + Math.ceil(Math.random() * 100000000),
        flag: "flag_vip",
        autoPlayerKey: "auto_player_key" + window.location.host,
        autoPlayerVal: "auto_player_value_" + window.location.host,
        currentParseIndex: "current_parse_index_" + window.location.host,
        successCountKey: "success_count_key_" + window.location.host,
        videoParseList: [
         {"name": "优质A", "type": "1,3", "url": "https://www.ckplayer.vip/jiexi/?url="},
         {"name": "通用无广", "type": "1,3", "url": "https://jx.nnxv.cn/tv.php?url="},
          {"name": "特供解析B", "type": "1,3", "url": "https://jx.77flv.cc/?url="},
            {"name": "特供解析A", "type": "1,3", "url": "https://jx.xmflv.com/?url="},
            {"name": "新1解析", "type": "1,3", "url": "https://jx.m3u8.tv/jiexi/?url="},
            {"name": "极速解析", "type": "1,3", "url": "https://jx.2s0.cn/player/?url="},
            {"name": "冰豆解析", "type": "1,3", "url": "https://bd.jx.cn/?url="},
            {"name": "973解析", "type": "1,3", "url": "https://jx.973973.xyz/?url="},
            {"name": "虾米视频解析", "type": "1,3", "url": "https://jx.xmflv.com/?url="},
            {"name": "CK", "type": "1,3", "url": "https://www.ckplayer.vip/jiexi/?url="},
            {"name": "七哥解析", "type": "1,3", "url": "https://jx.nnxv.cn/tv.php?url="},
            {"name": "夜幕", "type": "1,3", "url": "https://www.yemu.xyz/?url="},
            {"name": "盘古", "type": "1,3", "url": "https://www.pangujiexi.com/jiexi/?url="},
            {"name": "playm3u8", "type": "1,3", "url": "https://www.playm3u8.cn/jiexi.php?url="},
            {"name": "七七云解析", "type": "1,3", "url": "https://jx.77flv.cc/?url="},
            {"name": "芒果TV1", "type": "1,3", "url": "https://video.isyour.love/player/getplayer?url="},
            {"name": "芒果TV2", "type": "1,3","url":"https://im1907.top/?jx="},
            {"name": "HLS解析", "type": "1,3", "url": "https://jx.hls.one/?url="},
        ],
        playerContainers: [
            {
                host: "v.qq.com",
                container: "#mod_player,#player-container,.container-player",
                name: "Default",
                displayNodes: ["#mask_layer", ".mod_vip_popup", "#mask_layer", ".panel-tip-pay"]
            },
            {
                host: "m.v.qq.com",
                container: ".mod_player,#player",
                name: "Default",
                displayNodes: [".mod_vip_popup", "[class^=app_],[class^=app-],[class*=_app_],[class*=-app-],[class$=_app],[class$=-app]", "div[dt-eid=open_app_bottom]", "div.video_function.video_function_new", "a[open-app]", "section.mod_source", "section.mod_box.mod_sideslip_h.mod_multi_figures_h,section.mod_sideslip_privileges,section.mod_game_rec"]
            },

            {host: "w.mgtv.com", container: "#mgtv-player-wrap", name: "Default", displayNodes: []},
            {host: "www.mgtv.com", container: "#mgtv-player-wrap", name: "Default", displayNodes: []},
            {
                host: "m.mgtv.com",
                container: ".video-area",
                name: "Default",
                displayNodes: ["div.adFixedContain,div.ad-banner,div.m-list-graphicxcy.fstp-mark", "div[class^=mg-app],div#comment-id.video-comment div.ft,div.bd.clearfix,div.v-follower-info", "div.ht.mgui-btn.mgui-btn-nowelt", "div.personal", "div[data-v-41c9a64e]"]
            },
            {host: "www.bilibili.com", container: "#player_module,#bilibiliPlayer,#bilibili-player", name: "Default", displayNodes: []},
            {host: "m.bilibili.com", container: ".player-wrapper,.player-container,.mplayer", name: "Default", displayNodes: []},
            {host: "www.iqiyi.com", container: "#outlayer, .iqp-player-videolayer", name: "Default", displayNodes: ["#playerPopup", "#vipCoversBox" ,"div.iqp-player-vipmask", "div.iqp-player-paymask","div.iqp-player-loginmask", "div[class^=qy-header-login-pop]",".covers_cloudCover__ILy8R","#videoContent > div.loading_loading__vzq4j",".iqp-player-guide"]},
            {
                host: "m.iqiyi.com",
                container: ".m-video-player-wrap, .iqp-player-videolayer",
                name: "Default",
                displayNodes: ["div.m-iqyGuide-layer", "a[down-app-android-url]", "div.iqp-player-vipmask", ".loading_loading__vzq4j","[name=m-extendBar]", "[class*=ChannelHomeBanner]", "section.m-hotWords-bottom"]
            },
            {host: "www.iq.com", container: ".intl-video-wrap", name: "Default", displayNodes: []},
            {host: "v.youku.com", container: "#playerMouseWheel", name: "Default", displayNodes: ["#iframaWrapper"]},
            {host: "m.youku.com", container: "#playerMouseWheel,.h5-detail-player", name: "Default", displayNodes: []},
            {host: "tv.sohu.com", container: "#player", name: "Default", displayNodes: []},
            {host: "film.sohu.com", container: "#playerWrap", name: "Default", displayNodes: []},
            {host: "www.le.com", container: "#le_playbox", name: "Default", displayNodes: []},
            {host: "video.tudou.com", container: ".td-playbox", name: "Default", displayNodes: []},
            {host: "v.pptv.com", container: "#pptv_playpage_box", name: "Default", displayNodes: []},
            {host: "vip.pptv.com", container: ".w-video", name: "Default", displayNodes: []},
            {host: "www.wasu.cn", container: "#flashContent", name: "Default", displayNodes: []},
            {host: "www.acfun.cn", container: "#player", name: "Default", displayNodes: []},
            {host: "vip.1905.com", container: "#player,#vodPlayer", name: "Default", displayNodes: []},
            {host: "www.1905.com", container: "#player,#vodPlayer", name: "Default", displayNodes: []},
        ]
    };

    class BaseConsumer {
        constructor() {
            this.currentTryIndex = -1;
            this.autoTryTimer = null;
            this.successCounts = GM_getValue(_CONFIG_.successCountKey, {});
            this.parse = () => {
                util.findTargetEle('body')
                    .then((container) => this.preHandle(container))
                    .then((container) => this.generateStatusBox(container))
                    .then((container) => this.autoPlay(container))
                    .then((container) => this.postHandle(container));
            }
        }

        preHandle(container) {
            _CONFIG_.currentPlayerNode.displayNodes.forEach((item, index) => {
                util.findTargetEle(item)
                    .then((obj) => obj.style.display = 'none')
                    .catch(e => console.warn("不存在元素", e));
            });
            return new Promise((resolve, reject) => resolve(container));
        }

        generateStatusBox(container) {
            GM_addStyle(`
                #${_CONFIG_.statusBoxId} {
                    position: fixed;
                    top: 10px;
                    right: 10px;
                    z-index: 9999999;
                    background: rgba(0,0,0,0.7);
                    color: white;
                    padding: 8px 12px;
                    border-radius: 4px;
                    font-size: 12px;
                    display: flex;
                    align-items: center;
                    box-shadow: 0 2px 10px rgba(0,0,0,0.3);
                }
                #${_CONFIG_.statusBoxId} .status-indicator {
                    width: 8px;
                    height: 8px;
                    border-radius: 50%;
                    display: inline-block;
                    margin-right: 6px;
                }
                #${_CONFIG_.statusBoxId} .status-working {
                    background-color: #4CAF50;
                }
                #${_CONFIG_.statusBoxId} .status-error {
                    background-color: #F44336;
                }
                #${_CONFIG_.statusBoxId} .status-idle {
                    background-color: #FFC107;
                }
                #${_CONFIG_.statusBoxId} .loading-spinner {
                    width: 16px;
                    height: 16px;
                    border: 2px solid #f3f3f3;
                    border-top: 2px solid #3498db;
                    border-radius: 50%;
                    animation: spin 1s linear infinite;
                    margin-right: 6px;
                }
                
                #${_CONFIG_.switchBtnId} {
                    position: fixed;
                    top: 60px;
                    right: 10px;
                    z-index: 9999999;
                    width: 40px;
                    height: 40px;
                    border-radius: 50%;
                    background: #3498db;
                    color: white;
                    display: flex;
                    justify-content: center;
                    align-items: center;
                    cursor: pointer;
                    box-shadow: 0 2px 10px rgba(0,0,0,0.3);
                    transition: all 0.3s ease;
                    border: none;
                    outline: none;
                }
                
                #${_CONFIG_.switchBtnId}:hover {
                    transform: scale(1.1);
                    background: #2980b9;
                }
                
                #${_CONFIG_.switchBtnId}.success {
                    background: #2ecc71;
                }
                
                #${_CONFIG_.switchBtnId}.error {
                    background: #e74c3c;
                }
                
                #${_CONFIG_.switchBtnId}.loading {
                    background: #3498db;
                    animation: pulse 1.5s infinite;
                }
                
                #${_CONFIG_.switchBtnId} svg {
                    width: 24px;
                    height: 24px;
                    fill: white;
                }
                
                @keyframes pulse {
                    0% { transform: scale(1); }
                    50% { transform: scale(1.1); }
                    100% { transform: scale(1); }
                }
                
                @keyframes spin {
                    0% { transform: rotate(0deg); }
                    100% { transform: rotate(360deg); }
                }
            `);

            $(container).append(`
                <div id="${_CONFIG_.statusBoxId}">
                    <div class="loading-spinner"></div>
                    <span id="status-text">正在初始化解析器...</span>
                </div>
            `);
            
            // 添加切换按钮
            $(container).append(`
                <button id="${_CONFIG_.switchBtnId}" class="loading" title="切换解析源">
                    <svg viewBox="0 0 24 24">
                        <path d="M17.65,6.35C16.2,4.9,14.21,4,12,4c-4.42,0-7.99,3.58-7.99,8s3.57,8,7.99,8c3.73,0,6.84-2.55,7.73-6h-2.08 c-0.82,2.33-3.04,4-5.65,4c-3.31,0-6-2.69-6-6s2.69-6,6-6c1.66,0,3.14,0.69,4.22,1.78L13,11h7V4L17.65,6.35z"/>
                    </svg>
                </button>
            `);
            
            // 绑定按钮点击事件
            $(`#${_CONFIG_.switchBtnId}`).on('click', () => {
                this.switchToNextParser();
            });
            
            return new Promise((resolve, reject) => resolve(container));
        }

        updateStatus(text, statusClass) {
            const statusBox = $(`#${_CONFIG_.statusBoxId}`);
            if (statusBox.length) {
                statusBox.find("#status-text").text(text);
                if (statusClass) {
                    statusBox.find(".loading-spinner").remove();
                    statusBox.prepend(`<span class="status-indicator ${statusClass}"></span>`);
                }
            }
        }

        updateSwitchButton(status) {
            const btn = $(`#${_CONFIG_.switchBtnId}`);
            btn.removeClass("loading success error");
            btn.addClass(status);
        }

        autoPlay(container) {
            this.selectPlayer();
            return new Promise((resolve, reject) => resolve(container));
        }

        selectPlayer() {
            // 获取成功率最高的解析源
            let bestIndex = 0;
            let bestSuccessRate = -1;
            
            for (let i = 0; i < _CONFIG_.videoParseList.length; i++) {
                const successCount = this.successCounts[i] || 0;
                const successRate = successCount > 0 ? successCount / (successCount + 1) : 0;
                
                if (successRate > bestSuccessRate) {
                    bestSuccessRate = successRate;
                    bestIndex = i;
                }
            }
            
            let autoObj = _CONFIG_.videoParseList[bestIndex];
            let _th = this;
            if (autoObj.type.includes("1")) {
                setTimeout(function () {
                    _th.showPlayerWindow(autoObj, bestIndex);
                }, 1000);
            }
        }

        showPlayerWindow(videoObj, index) {
            this.currentTryIndex = index;
            this.updateStatus(`正在尝试: ${videoObj.name}`, "status-working");
            this.updateSwitchButton("loading");
            
            util.findTargetEle(_CONFIG_.currentPlayerNode.container)
                .then((container) => {
                    const type = videoObj.type;
                    let url = videoObj.url + window.location.href;
                    if (type.includes("1")) {
                        $(container).empty();
                        util.reomveVideo();
                        let iframeDivCss = "width:100%;height:100%;z-index:999999;position:relative;";
                        if (_CONFIG_.isMobile) {
                            iframeDivCss = "width:100%;height:450px;z-index:999999;position:relative;";
                        }
                        if (_CONFIG_.isMobile && window.location.href.indexOf("iqiyi.com") !== -1) {
                            iframeDivCss = "width:100%;height:450px;z-index:999999;margin-top:-56.25%;position:relative;";
                        }
                        
                        // 添加加载动画
                        $(container).append(`
                            <div style="${iframeDivCss}">
                                <div class="loading-container" style="position:absolute;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.7);z-index:99999999;display:flex;justify-content:center;align-items:center;flex-direction:column;">
                                    <div class="loading-spinner" style="width:40px;height:40px;border:4px solid #f3f3f3;border-top:4px solid #3498db;border-radius:50%;animation:spin 1s linear infinite;"></div>
                                    <div style="color:white;margin-top:10px;">正在尝试解析: ${videoObj.name}</div>
                                </div>
                                <iframe id="iframe-player-4a5b6c" src="${url}" style="border:none;width:100%;height:100%;" allowfullscreen="true"></iframe>
                            </div>
                        `);
                        
                        const iframe = $(container).find("#iframe-player-4a5b6c")[0];
                        const loadingContainer = $(container).find(".loading-container");
                        
                        // 设置超时检测
                        const timeout = setTimeout(() => {
                            loadingContainer.hide();
                            this.handleParseFailure(index, container);
                        }, 10000);
                        
                        // 监听iframe加载完成
                        iframe.onload = () => {
                            clearTimeout(timeout);
                            loadingContainer.hide();
                            
                            // 记录解析成功
                            this.recordParseSuccess(index);
                            
                            // 更新状态
                            this.updateStatus(`解析成功: ${videoObj.name}`, "status-working");
                            this.updateSwitchButton("success");
                        };
                    }
                });
        }
        
        handleParseFailure(currentIndex, container) {
            // 记录解析失败
            this.recordParseFailure(currentIndex);
            
            // 查找下一个可用的解析源
            let nextIndex = -1;
            for (let i = 0; i < _CONFIG_.videoParseList.length; i++) {
                const idx = (currentIndex + i + 1) % _CONFIG_.videoParseList.length;
                if (_CONFIG_.videoParseList[idx].type.includes("1")) {
                    nextIndex = idx;
                    break;
                }
            }
            
            if (nextIndex !== -1) {
                // 显示下一个解析源
                const nextObj = _CONFIG_.videoParseList[nextIndex];
                this.showPlayerWindow(nextObj, nextIndex);
                
                // 更新状态
                this.updateStatus(`解析失败,尝试: ${nextObj.name}`, "status-error");
                this.updateSwitchButton("error");
                
                // 显示错误通知
                GM_notification({
                    text: `解析失败,正在尝试: ${nextObj.name}`,
                    title: "VIP解析",
                    timeout: 3000
                });
            } else {
                // 没有可用的解析源
                this.updateStatus("所有解析源尝试失败", "status-error");
                this.updateSwitchButton("error");
                GM_notification({
                    text: "所有解析源尝试失败,请刷新页面重试",
                    title: "VIP解析",
                    timeout: 5000
                });
            }
        }
        
        recordParseSuccess(index) {
            // 更新成功率统计
            this.successCounts[index] = (this.successCounts[index] || 0) + 1;
            GM_setValue(_CONFIG_.successCountKey, this.successCounts);
        }
        
        recordParseFailure(index) {
            // 更新成功率统计
            this.successCounts[index] = this.successCounts[index] || 0;
            GM_setValue(_CONFIG_.successCountKey, this.successCounts);
        }
        
        switchToNextParser() {
            if (this.currentTryIndex === -1) return;
            
            // 查找下一个可用的解析源
            let nextIndex = -1;
            for (let i = 0; i < _CONFIG_.videoParseList.length; i++) {
                const idx = (this.currentTryIndex + i + 1) % _CONFIG_.videoParseList.length;
                if (_CONFIG_.videoParseList[idx].type.includes("1")) {
                    nextIndex = idx;
                    break;
                }
            }
            
            if (nextIndex !== -1) {
                // 显示下一个解析源
                const nextObj = _CONFIG_.videoParseList[nextIndex];
                this.showPlayerWindow(nextObj, nextIndex);
                
                // 更新状态
                this.updateStatus(`手动切换至: ${nextObj.name}`, "status-working");
                this.updateSwitchButton("loading");
                
                // 显示通知
                GM_notification({
                    text: `已切换到: ${nextObj.name}`,
                    title: "VIP解析",
                    timeout: 2000
                });
            }
        }

        postHandle(container) {
            util.urlChangeReload();
        }

    }

    class DefaultConsumer extends BaseConsumer {
    }

    return {
        start: () => {
            GM_setValue(_CONFIG_.flag, null);
            let mallCase = 'Default';
            let playerNode = _CONFIG_.playerContainers.filter(value => value.host === window.location.host);
            if (playerNode === null || playerNode.length <= 0) {
                console.warn(window.location.host + "该网站暂不支持,请联系作者,作者将会第一时间处理(注意:请记得提供有问题的网址)");
                return;
            }
            _CONFIG_.currentPlayerNode = playerNode[0];
            mallCase = _CONFIG_.currentPlayerNode.name;
            const targetConsumer = eval(`new ${mallCase}Consumer`);
            targetConsumer.parse();
        }
    }

})();

(function () {
    superVip.start();
})();