// ==UserScript== // @name 智能YouTube全站广告拦截器 // @version 2.2 // @description 精准广告拦截,支持多平台保护 // @icon https://www.youtube.com/favicon.ico // @author little fool // @match *://*/* // @grant GM_addStyle // @grant unsafeWindow // @run-at document-start // @namespace https://yournamespace.com // @license MIT // @downloadURL none // ==/UserScript== (function() { 'use strict'; // 样式增强 GM_addStyle(` .adblocker-status-icon { position: fixed; bottom: 20px; right: 20px; width: 40px; height: 40px; background: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0Ij48cGF0aCBkPSJNMjEuNTggNy4xOWMtLjIzLS44Ni0uOTQtMS41MS0xLjgxLTEuNzNDMTguMjQ1IDAgNSAwIDUgMHMtMTguMjQgMC0xOS43Ny40NmMtLjg3LjIyLTEuNTguODctMS44IDEuNzNDMCA4LjcxIDAgMTIgMCAxMnMwIDMuMjkuMDMgNC44MWMuMjIuODYuOTMgMS41MSAxLjggMS43MyAxLjUzLjQ4IDE5Ljc3LjQ4IDE5Ljc3LjQ4czE4LjI0IDAgMTkuNzctLjQ2Yy44Ny0uMjIgMS41OC0uODcgMS44LTEuNzMuMDMtMS41Mi4wMy0zLjI5LjAzLTQuODFzLS4wMS0zLjI5LS4wMy00Ljgxek0xMCAxNWw4LjgtNUwxMCA1djEweiIgZmlsbD0iI2ZmMDAwMCIvPjwvc3ZnPg==') no-repeat center/cover; cursor: pointer; z-index: 99999; opacity: 0.8; transition: all 0.3s; border-radius: 50%; box-shadow: 0 2px 5px rgba(0,0,0,0.3); transform: translateY(0); } .adblocker-status-icon:hover { opacity: 1; transform: translateY(-3px) scale(1.1); } .adblocker-tooltip { position: fixed; bottom: 70px; right: 20px; background: rgba(0,0,0,0.9); color: #fff; padding: 10px 15px; border-radius: 6px; font-size: 13px; display: none; white-space: nowrap; backdrop-filter: blur(2px); border: 1px solid rgba(255,255,255,0.1); } `); // 安全配置中心 const SecurityConfig = { protectedDomains: { 'youtube.com': { icon: true, selectors: [ 'ytd-display-ad-renderer', '#player-ads', '.ytp-ad-module', 'ytd-promoted-sparkles-web-renderer', 'div.ytd-in-feed-ad-layout-renderer', 'ytd-ad-slot-renderer' ], networkPatterns: [ /doubleclick\.net\/ddm\/activity/, /youtube\.com\/api\/stats\/ads/, /google\.com\/pagead\// ] }, 'baidu.com': { selectors: [ '#kw', '#form', '.s_ipt', '.s_btn', '.bdsug', '[name="wd"]' ], containers: ['#form', '.s_form_wrapper'] } }, adSelectors: [ '[class*="ad-"]:not([class*="adaptive"])', '[id*="Ad"]:not([id*="Adapter"])', 'iframe[src*="/ad/"]', 'div[data-ad-target]', 'ins.adsbygoogle' ] }; class AdBlocker { constructor() { this.currentHost = window.location.hostname; this.iconInstance = null; this.tooltipInstance = null; this.init(); } init() { this.setupProtection(); this.setupIcon(); this.setupListeners(); } setupProtection() { // 初始化广告拦截 this.setupDOMScanner(); this.setupNetworkBlocker(); } setupDOMScanner() { // 创建Mutation Observer const observer = new MutationObserver(mutations => { mutations.forEach(mutation => { this.handleMutations(mutation.addedNodes); }); this.forceScan(); }); observer.observe(document, { childList: true, subtree: true, attributes: false }); // 初始扫描 this.forceScan(); } handleMutations(nodes) { nodes.forEach(node => { if (node.nodeType === 1) this.scanElement(node); }); } scanElement(element) { const selectors = this.getCurrentSelectors(); element.querySelectorAll(selectors).forEach(el => { if (!this.isProtected(el)) { this.safeRemove(el); } }); } safeRemove(element) { try { if (element?.parentNode) { element.parentNode.removeChild(element); console.debug('元素已移除:', element); } } catch (e) { console.warn('元素移除失败:', e); } } getCurrentSelectors() { const base = SecurityConfig.adSelectors; const domain = this.getDomainConfig(); return domain?.selectors ? [...base, ...domain.selectors].join(', ') : base.join(', '); } setupNetworkBlocker() { // 拦截fetch const origFetch = window.fetch; window.fetch = async (input, init) => { const url = input.url || input; if (this.isAdRequest(url)) { console.log('[拦截] 网络请求:', url); return new Response(null, { status: 403 }); } return origFetch(input, init); }; // 拦截XHR const origOpen = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function(method, url) { this._requestUrl = url; return origOpen.apply(this, arguments); }; const origSend = XMLHttpRequest.prototype.send; XMLHttpRequest.prototype.send = function(...args) { if (this._requestUrl && this.isAdRequest(this._requestUrl)) { console.log('[拦截] XHR请求:', this._requestUrl); this.abort(); return; } return origSend.apply(this, args); }; } isAdRequest(url) { const patterns = this.getDomainConfig()?.networkPatterns || []; return patterns.some(p => p.test(url)); } setupIcon() { if (!this.shouldShowIcon()) return; // 创建图标 this.iconInstance = document.createElement('div'); this.iconInstance.className = 'adblocker-status-icon'; // 创建工具提示 this.tooltipInstance = document.createElement('div'); this.tooltipInstance.className = 'adblocker-tooltip'; this.tooltipInstance.textContent = '广告拦截已启用 ✓'; document.body.append(this.iconInstance, this.tooltipInstance); this.setupIconEvents(); } setupIconEvents() { // 悬停事件 this.iconInstance.addEventListener('mouseenter', () => { this.tooltipInstance.style.display = 'block'; }); this.iconInstance.addEventListener('mouseleave', () => { this.tooltipInstance.style.display = 'none'; }); // 点击事件 this.iconInstance.addEventListener('click', () => { this.showStatusInfo(); }); } showStatusInfo() { this.tooltipInstance.innerHTML = `
拦截版本: v2.2
最后扫描: ${new Date().toLocaleTimeString()}
已拦截请求: ${this.blockedCount || 0}
`; this.tooltipInstance.style.display = 'block'; setTimeout(() => { this.tooltipInstance.style.display = 'none'; }, 2500); } shouldShowIcon() { return this.getDomainConfig()?.icon === true; } getDomainConfig() { return Object.entries(SecurityConfig.protectedDomains) .find(([domain]) => this.currentHost.includes(domain))?.[1]; } forceScan() { this.scanElement(document.documentElement); } setupListeners() { // SPA路由监听 let lastUrl = location.href; new MutationObserver(() => { if (location.href !== lastUrl) { lastUrl = location.href; this.currentHost = new URL(location.href).hostname; this.forceScan(); this.updateIconVisibility(); } }).observe(document, { subtree: true, childList: true }); } updateIconVisibility() { if (this.shouldShowIcon() && !this.iconInstance) { this.setupIcon(); } else if (!this.shouldShowIcon() && this.iconInstance) { this.iconInstance.remove(); this.tooltipInstance.remove(); this.iconInstance = null; this.tooltipInstance = null; } } isProtected(element) { const domainConfig = this.getDomainConfig(); if (!domainConfig) return false; return domainConfig.selectors?.some(s => element.matches(s)) || domainConfig.containers?.some(c => element.closest(c)); } } // 启动实例 new AdBlocker(); })();