YouTube广告拦截器

优化代码,增强可维护性,无API依赖的极简高效广告拦截方案

目前为 2025-03-31 提交的版本。查看 最新版本

// ==UserScript==
// @name         YouTube广告拦截器
// @namespace    safe-adblock
// @version      4.2
// @match        *://*.youtube.com/*
// @grant        none
// @run-at       document-start
// @description  优化代码,增强可维护性,无API依赖的极简高效广告拦截方案
// ==/UserScript==

(function () {
    'use strict';

    // 广告相关的CSS选择器
    const AD_SELECTORS = [
        'ytd-ad-slot-renderer',
        'div.ytd-promoted-sparkles-web-renderer',
        '[data-ad-metadata]',
        'div#player-ads.ytd-watch:not(#movie_player)',
        'ytd-rich-section-renderer:has(ytd-ad-)',
        'div[class*="-ad-"]:not([data-legitimate])',
        'div.ytp-ad-module'
    ];

    /**
     * 注入广告隐藏和播放器保护的样式
     */
    const injectStyles = () => {
        const styleContent = `
            /* 广告隐藏规则 */
            ${AD_SELECTORS.join(', ')} {
                transform: scale(0) !important;
                height: 0 !important;
                width: 0 !important;
                opacity: 0 !important;
                pointer-events: none !important;
                position: absolute !important;
                z-index: -1 !important;
            }
            
            /* 播放器核心保护规则 */
            #movie_player, .html5-video-player {
                position: static !important;
                width: 100% !important;
                height: 0 !important;
                padding-bottom: 56.25% !important; /* 16:9比例 */
                min-height: auto !important;
                overflow: visible !important;
            }
            
            /* 视频自适应容器 */
            .html5-video-container {
                position: absolute !important;
                top: 0 !important;
                left: 0 !important;
                width: 100% !important;
                height: 100% !important;
            }
            
            /* 修复全屏显示 */
            .ytp-fullscreen #movie_player {
                padding-bottom: 0 !important;
                height: 100vh !important;
            }
            
            /* 防止推荐栏重叠 */
            ytd-watch-flexy[theater] #secondary.ytd-watch-flexy {
                margin-top: 60px !important;
                z-index: 500 !important;
            }
        `;
        const styleElement = document.createElement('style');
        styleElement.textContent = styleContent;
        document.head.appendChild(styleElement);
    };

    /**
     * 播放器保护模块
     */
    const playerProtector = {
        observer: null,
        init() {
            this.observePlayerSize();
            this.patchFullscreenAPI();
        },
        /**
         * 使用 ResizeObserver 监听播放器大小变化
         */
        observePlayerSize() {
            this.observer = new ResizeObserver(entries => {
                entries.forEach(entry => {
                    const video = entry.target.querySelector('video');
                    if (video) {
                        this.adjustVideoSize(video);
                    }
                });
            });

            const checkAndObservePlayer = () => {
                const player = document.getElementById('movie_player');
                if (player && !player.hasAttribute('data-observed')) {
                    player.setAttribute('data-observed', 'true');
                    this.observer.observe(player);
                    const video = player.querySelector('video');
                    if (video) {
                        this.adjustVideoSize(video);
                    }
                }
            };
            // 初次检查和定时检查
            checkAndObservePlayer();
            setInterval(checkAndObservePlayer, 3000);
        },
        /**
         * 调整视频与容器尺寸
         * @param {HTMLVideoElement} video 
         */
        adjustVideoSize(video) {
            const container = video.closest('.html5-video-container');
            if (container) {
                container.style.cssText = `
                    width: 100% !important;
                    height: 100% !important;
                    overflow: hidden !important;
                `;
            }
            video.style.cssText = `
                width: 100% !important;
                height: 100% !important;
                object-fit: contain !important;
            `;
        },
        /**
         * 修改全屏API使播放器在全屏时正常显示
         */
        patchFullscreenAPI() {
            const originalRequestFullscreen = Element.prototype.requestFullscreen;
            Element.prototype.requestFullscreen = function() {
                const player = document.getElementById('movie_player');
                if (player && player.contains(this)) {
                    player.style.paddingBottom = '0';
                    player.style.height = '100vh';
                }
                return originalRequestFullscreen.apply(this, arguments);
            };
        }
    };

    /**
     * 广告清理模块,使用 MutationObserver 动态移除广告元素
     */
    const adCleaner = {
        observer: null,
        init() {
            this.observer = new MutationObserver(mutations => {
                mutations.forEach(mutation => {
                    mutation.addedNodes.forEach(node => {
                        if (node.nodeType === 1) {
                            this.cleanAds(node);
                        }
                    });
                });
            });
            this.observer.observe(document, { childList: true, subtree: true });
        },
        /**
         * 清理指定节点下的广告元素
         * @param {HTMLElement} root 
         */
        cleanAds(root) {
            AD_SELECTORS.forEach(selector => {
                const ads = root.querySelectorAll(selector);
                ads.forEach(ad => {
                    // 移除子节点并隐藏元素
                    ad.replaceChildren();
                    ad.style.cssText = 'display: none !important';
                });
            });
        }
    };

    // 初始化所有模块
    const init = () => {
        injectStyles();
        playerProtector.init();
        adCleaner.init();
    };

    // 确保DOM加载完毕后执行初始化
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        init();
    }
})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址