您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
[13模块完整版] 动态检测、框架过滤、堆叠拦截、第三方拦截四大系统,增强广告拦截
当前为
// ==UserScript== // @name 广告终结者 v2.0 // @namespace http://tampermonkey.net/ // @version 2.0 // @description [13模块完整版] 动态检测、框架过滤、堆叠拦截、第三方拦截四大系统,增强广告拦截 // @author TMHhz // @match *://*/* // @license GPLv3 // @grant GM_registerMenuCommand // @grant GM_setValue // @grant GM_getValue // @grant GM_notification // ==/UserScript== (function() { 'use strict'; // 核心配置 const CONFIG = { maxLogs: 100, adKeywords: [ 'ad', 'ads', 'advert', 'banner', 'popup', '推广', '广告', 'gg', 'advertisement', 'sponsor', '推荐', 'adv', 'guanggao', 'syad', 'bfad', '男男', '女女', '弹窗', '悬浮', '浮动', '浮窗', '葡京', 'pop', 'sticky', 'fixed', 'tip', 'tips', 'adbox', 'adsense', 'adserver', 'advertmarket', 'advertising', 'cookie-sync', '国产', '偷拍', '黑料', '横幅' ], checkAttributes: [ 'id', 'class', 'src', 'href', 'data-ad', 'name', 'data-src', 'data-url', 'alt', 'title', 'onclick', 'style' ], protectionRules: { minWidth: 50, minHeight: 20, iframeSizeThreshold: 2, zIndexThreshold: 50, sizeThresholdRatio: 0.15, similarityThreshold: 0.8, dynamicIdLength: 10, dynamicIdDigits: 5, fixedPositionThreshold: 2, floatingKeywords: ['float', '悬浮', '弹窗', '浮窗', '浮动','横幅','fixed','sticky','tip','tips','pop'], adImagePatterns: ['/*.gif', '/*.webp', '/*.swf'], adContainerSelectors: ['[id*="side"]', '[class*="side"]'], viewportEdgeThreshold: 10, maxFrameDepth: 3, textAdKeywords: ['限时优惠', '立即下载', '免费领取', 'vx:', '点击咨询', '低至1折', '加群', '抢购', '微信', 'telegram', '国产', '偷拍', '黑料'] }, whitelist: { scriptNamespaces: ['pswMgrDialog', 'userscript-'], protectedAttributes: [ {name: 'id', values: ['pswMgrDialog', 'userscript-quickFill']}, {name: 'class', values: ['userscript-quickFill']} ], selectors: ['#pswMgrDialog', '.userscript-quickFill', '.userscript-pswmgrDlg'], thirdparty: ['cdn.bootcss.com', 'unpkg.com'] }, defaultSettings: { // 动态检测系统 dynamicIdDetection: true, attributeSimilarity: true, sizeAnomaly: true, adAttributeDetection: true, // 框架过滤系统 iframeAttributeCheck: true, parentContainerCheck: true, nestedFrameDetection: true, // 堆叠拦截系统 highZIndexDetection: true, fixedPositionCheck: true, overlayDetection: true, floatingLayerCheck: true, // 第三方拦截 thirdpartyCheck: true, cookieSyncDetection: true, // 增强功能 floatingAdDetection: true, imageAdDetection: true, sidebarAdDetection: true, textAdDetection: true } }; // ======================= 工具类 ======================= class AdUtils { static safeRemove(node, module, reason) { if (!node || !node.parentNode || this.isWhitelisted(node)) { console.debug('[拦截跳过] 白名单元素:', node); return false; } try { Logger.logRemoval({ module, element: { tag: node.tagName, id: node.id, class: node.className, html: node.outerHTML.slice(0, 500) }, reason }); node.parentNode.removeChild(node); this.cleanAncestors(node.parentNode); console.log('[成功移除]', module, node); return true; } catch (e) { console.error('元素移除失败:', e); return false; } } static cleanAncestors(node) { let current = node; while (current && current !== document.documentElement) { if (current.children.length === 0 && !current.hasAttribute('data-keep-empty')) { const parent = current.parentNode; parent?.removeChild(current); current = parent; } else { break; } } } static isWhitelisted(element) { let currentElement = element; while (currentElement && currentElement !== document.documentElement) { const src = currentElement.getAttribute('src'); if (src && CONFIG.whitelist.thirdparty.some(domain => src.includes(domain))) return true; if (CONFIG.whitelist.selectors.some(s => currentElement.matches(s))) return true; if (CONFIG.whitelist.protectedAttributes.some(attr => { const attrValue = currentElement.getAttribute(attr.name); return attrValue && attr.values.some(v => attr.name === 'class' ? currentElement.classList.contains(v) : attrValue.startsWith(v) ); })) return true; if (CONFIG.whitelist.scriptNamespaces.some(ns => { const id = currentElement.id || ''; const className = currentElement.className || ''; return id.startsWith(ns) || className.startsWith(ns); })) return true; currentElement = currentElement.parentElement; } return false; } static calculateSimilarity(a, b) { const setA = new Set(a.split('')); const setB = new Set(b.split('')); const intersection = new Set([...setA].filter(x => setB.has(x))); return intersection.size / Math.max(setA.size, setB.size); } } // ======================= 第三方拦截模块 ======================= class ThirdpartyInterceptor { constructor() { this.baseHost = this.getCurrentBaseHost(); this.initObserver(); } getCurrentBaseHost() { const host = location.hostname; return this.isIP(host) ? host : this.getBaseDomain(host); } isIP(host) { return /^(?:\d{1,3}\.){3}\d{1,3}$/.test(host); } getBaseDomain(url) { try { const parsed = new URL(url.startsWith('http') ? url : `http://${url}`); const parts = parsed.hostname.split('.'); if (parts.length <= 1) return parsed.hostname; return parts.slice(-2).join('.'); } catch { return this.baseHost; } } isThirdparty(src) { if (!src || CONFIG.whitelist.thirdparty.some(d => src.includes(d))) return false; try { return this.getBaseDomain(src) !== this.baseHost; } catch { return false; } } processNode(node) { const tag = node.tagName.toUpperCase(); if (['SCRIPT', 'IFRAME'].includes(tag)) { const src = node.getAttribute('src'); if (src && this.isThirdparty(src)) { AdUtils.safeRemove(node, 'thirdparty', { type: '第三方资源', detail: `拦截源: ${this.getBaseDomain(src)}` }); } } } initObserver() { const observer = new MutationObserver(mutations => { mutations.forEach(m => { m.addedNodes.forEach(node => { if (node.nodeType === Node.ELEMENT_NODE) { this.processNode(node); node.querySelectorAll('script, iframe').forEach(n => this.processNode(n)); } }); }); }); observer.observe(document, { childList: true, subtree: true }); document.querySelectorAll('script, iframe').forEach(n => this.processNode(n)); } } // ======================= 核心拦截系统 ======================= class CoreCleaner { constructor() { if (DomainConfig.getConfig('thirdpartyCheck')) { this.thirdpartyInterceptor = new ThirdpartyInterceptor(); } if (DomainConfig.getConfig('cookieSyncDetection')) { this.cookieSyncCheck(); } if (this.isAnyModuleEnabled()) { this.initEnhancedObserver(); this.initialCleanup(); } } isAnyModuleEnabled() { return Object.keys(CONFIG.defaultSettings).some( key => DomainConfig.getConfig(key) ); } initEnhancedObserver() { this.observer = new MutationObserver(mutations => { mutations.forEach(m => { m.addedNodes.forEach(node => { if (node.nodeType === Node.ELEMENT_NODE) { if (node.shadowRoot) { this.observer.observe(node.shadowRoot, { childList: true, subtree: true }); } this.checkGenericElements(node); if (node.tagName === 'IFRAME') this.checkIframes(node); if (['DIV', 'P', 'SPAN'].includes(node.tagName)) this.checkTextAds(node); } }); }); }); this.observer.observe(document, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class', 'id', 'src', 'href'] }); } initialCleanup() { if (!this.isAnyModuleEnabled()) return; this.runDetectionSystems(); this.checkElements('iframe', this.checkIframes.bind(this)); this.checkElements('*', this.checkGenericElements.bind(this)); this.checkElements('img', this.checkImageAds.bind(this)); this.checkElements('*', this.checkFloatingAds.bind(this)); this.checkSidebarContainers(); this.checkElements('div,p,span', this.checkTextAds.bind(this)); } runDetectionSystems() { if (DomainConfig.getConfig('highZIndexDetection')) this.checkHighZIndex(); if (DomainConfig.getConfig('fixedPositionCheck')) this.checkFixedPosition(); if (DomainConfig.getConfig('overlayDetection')) this.checkOverlay(); if (DomainConfig.getConfig('floatingLayerCheck')) this.checkFloatingLayers(); } checkElements(selector, checker) { if (!this.isAnyModuleEnabled()) return; document.querySelectorAll(selector).forEach(node => checker(node)); } // ========== 框架过滤系统 ========== checkIframes(iframe) { if (DomainConfig.getConfig('iframeAttributeCheck')) { this.checkIframeAttributes(iframe); } if (DomainConfig.getConfig('parentContainerCheck')) { this.checkParentContainers(iframe); } if (DomainConfig.getConfig('nestedFrameDetection')) { this.checkNestedFrames(iframe); } } checkParentContainers(iframe) { const parents = ['div', 'section', 'article'] .map(s => iframe.closest(s)) .filter(Boolean); parents.forEach(parent => { if (!AdUtils.isWhitelisted(parent)) { AdUtils.safeRemove(parent, 'frame-parent', { type: '父容器过滤', detail: '可疑iframe容器' }); } }); } checkIframeAttributes(iframe) { const hasAdSrc = CONFIG.adKeywords.some(kw => iframe.src.includes(kw)); const isHidden = iframe.offsetWidth < CONFIG.protectionRules.iframeSizeThreshold || iframe.offsetHeight < CONFIG.protectionRules.iframeSizeThreshold; if (isHidden || hasAdSrc) { AdUtils.safeRemove(iframe, 'frame-attr', { type: 'iframe属性', detail: hasAdSrc ? `广告源: ${iframe.src.slice(0, 50)}` : `隐藏iframe: ${iframe.offsetWidth}x${iframe.offsetHeight}` }); } } checkNestedFrames(iframe) { try { const depth = this.getFrameDepth(iframe); if (depth > CONFIG.protectionRules.maxFrameDepth) { AdUtils.safeRemove(iframe, 'nested-frame', { type: '嵌套框架', detail: `嵌套层级: ${depth}层` }); } } catch (e) { console.log('框架深度检测异常:', e); } } getFrameDepth(node) { let depth = 0; let currentNode = node; while (currentNode.parentNode) { if (currentNode.tagName === 'IFRAME') depth++; currentNode = currentNode.parentNode; } return depth; } // ========== 动态检测系统 ========== checkGenericElements(element) { if (DomainConfig.getConfig('dynamicIdDetection')) { this.checkDynamicId(element); } if (DomainConfig.getConfig('attributeSimilarity')) { this.checkAttributeSimilarity(element); } if (DomainConfig.getConfig('sizeAnomaly')) { this.checkSizeAnomaly(element); } if (DomainConfig.getConfig('adAttributeDetection')) { this.checkAdAttributes(element); } } checkDynamicId(element) { const id = element.id || ''; if (id.length > CONFIG.protectionRules.dynamicIdLength || /\d{5,}/.test(id)) { AdUtils.safeRemove(element, 'dynamic-id', { type: '动态ID检测', detail: `ID特征异常: ${id.slice(0, 50)}` }); } } checkAttributeSimilarity(element) { const id = element.id || ''; const className = element.className || ''; if (AdUtils.calculateSimilarity(id, className) > CONFIG.protectionRules.similarityThreshold) { AdUtils.safeRemove(element, 'attr-similarity', { type: '属性相似度', detail: `ID与class相似度过高` }); } } checkSizeAnomaly(element) { const rect = element.getBoundingClientRect(); if (rect.width * rect.height > window.innerWidth * window.innerHeight * CONFIG.protectionRules.sizeThresholdRatio) { AdUtils.safeRemove(element, 'size-anomaly', { type: '尺寸异常', detail: `占用面积 ${Math.round(rect.width*rect.height)}px²` }); } } checkAdAttributes(element) { const attrCheck = CONFIG.checkAttributes.find(attr => { const value = element.getAttribute(attr) || ''; return CONFIG.adKeywords.some(kw => value.includes(kw)); }); if (attrCheck) { AdUtils.safeRemove(element, 'attr-match', { type: '属性匹配', attribute: attrCheck, value: element.getAttribute(attrCheck).slice(0, 100) }); } } // ========== 堆叠拦截系统 ========== checkHighZIndex() { document.querySelectorAll('body *').forEach(el => { const zIndex = parseInt(getComputedStyle(el).zIndex); if (!isNaN(zIndex) && zIndex > CONFIG.protectionRules.zIndexThreshold) { AdUtils.safeRemove(el, 'z-index', { type: '高堆叠', detail: `z-index: ${zIndex}` }); } }); } checkFixedPosition() { const fixedElements = []; document.querySelectorAll('*').forEach(el => { const style = getComputedStyle(el); if (style.position === 'fixed' && !AdUtils.isWhitelisted(el)) { fixedElements.push(el); } }); if (fixedElements.length > CONFIG.protectionRules.fixedPositionThreshold) { fixedElements.forEach(el => { AdUtils.safeRemove(el, 'fixed-pos', { type: '过量固定元素', detail: `发现${fixedElements.length}个固定元素` }); }); } } checkOverlay() { document.querySelectorAll('div, section').forEach(el => { const style = getComputedStyle(el); if (style.backgroundColor !== 'rgba(0, 0, 0, 0)' && parseFloat(style.opacity) > 0.5 && el.offsetWidth >= window.innerWidth * 0.8) { AdUtils.safeRemove(el, 'overlay', { type: '遮罩层', detail: `背景色: ${style.backgroundColor}` }); } }); } checkFloatingLayers() { document.querySelectorAll('*').forEach(el => { const style = getComputedStyle(el); if (style.position === 'fixed' && (el.offsetWidth < 200 || el.offsetHeight < 100)) { AdUtils.safeRemove(el, 'floating-layer', { type: '悬浮层', detail: `小型浮动元素: ${el.offsetWidth}x${el.offsetHeight}` }); } }); } // ========== 增强功能模块 ========== checkFloatingAds(element) { if (!DomainConfig.getConfig('floatingAdDetection')) return; const style = getComputedStyle(element); const isFixed = style.position === 'fixed'; const isSticky = style.position === 'sticky'; const hasFloatingClass = CONFIG.protectionRules.floatingKeywords.some(kw => element.className.includes(kw) || element.id.includes(kw) ); const rect = element.getBoundingClientRect(); const edgeDetected = rect.top <= CONFIG.protectionRules.viewportEdgeThreshold || rect.bottom >= window.innerHeight - CONFIG.protectionRules.viewportEdgeThreshold || rect.left <= CONFIG.protectionRules.viewportEdgeThreshold || rect.right >= window.innerWidth - CONFIG.protectionRules.viewportEdgeThreshold; if ((isFixed || isSticky || hasFloatingClass) && edgeDetected) { AdUtils.safeRemove(element, 'floating-ad', { type: '浮动广告', detail: `定位方式: ${style.position}, 位置: ${Math.round(rect.top)}px` }); } } checkImageAds(img) { if (!DomainConfig.getConfig('imageAdDetection')) return; const src = img.src.toLowerCase(); const isAdImage = CONFIG.protectionRules.adImagePatterns.some(pattern => src.endsWith(pattern) || src.includes('adimg') ); const adDimensions = [ [728, 90], [300, 250], [336, 280], [250, 250], [120, 600], [160, 600], [468, 60], [900, 100] ]; const isAdSize = adDimensions.some(([w, h]) => Math.abs(img.width - w) < 10 && Math.abs(img.height - h) < 10 ); if (isAdImage || isAdSize) { AdUtils.safeRemove(img, 'image-ad', { type: '图片广告', detail: `尺寸: ${img.width}x${img.height}, 源: ${src.slice(0, 50)}` }); } } checkSidebarContainers() { if (!DomainConfig.getConfig('sidebarAdDetection')) return; document.querySelectorAll(CONFIG.protectionRules.adContainerSelectors.join(',')).forEach(container => { const rect = container.getBoundingClientRect(); const isSidePositioned = rect.left <= 10 || rect.right >= window.innerWidth - 10; if (isSidePositioned && container.offsetHeight > 200) { AdUtils.safeRemove(container, 'sidebar-ad', { type: '侧边栏容器', detail: `位置: ${Math.round(rect.left)}px, 高度: ${container.offsetHeight}px` }); } }); } checkTextAds(element) { if (!DomainConfig.getConfig('textAdDetection')) return; const text = element.textContent.toLowerCase(); const isSuspicious = CONFIG.protectionRules.textAdKeywords.some(kw => text.includes(kw.toLowerCase()) ); if (isSuspicious && element.children.length === 0) { AdUtils.safeRemove(element, 'text-ad', { type: '文本广告', detail: `包含关键词: ${text.slice(0,30)}` }); } } cookieSyncCheck() { document.querySelectorAll('script').forEach(script => { const src = script.getAttribute('src'); if (src && src.includes('cookie') && src.includes('sync')) { AdUtils.safeRemove(script, 'cookie-sync', { type: 'Cookie同步', detail: `检测到同步脚本: ${src.slice(0, 50)}` }); } }); } destructor() { if (this.observer) this.observer.disconnect(); } } // ======================= 配置系统 ======================= class DomainConfig { static get currentDomain() { return location.hostname.replace(/^www\./, ''); } static getConfig(key) { const allConfigs = GM_getValue('domainConfigs', {}); const domainConfig = allConfigs[this.currentDomain] || {...CONFIG.defaultSettings}; return key in domainConfig ? domainConfig[key] : CONFIG.defaultSettings[key]; } static updateConfig(key, value) { const allConfigs = GM_getValue('domainConfigs', {}); if (!allConfigs[this.currentDomain]) { allConfigs[this.currentDomain] = {...CONFIG.defaultSettings}; } allConfigs[this.currentDomain][key] = value; GM_setValue('domainConfigs', allConfigs); } static resetConfig() { const allConfigs = GM_getValue('domainConfigs', {}); delete allConfigs[this.currentDomain]; GM_setValue('domainConfigs', allConfigs); } } // ======================= 用户界面 ======================= class UIController { static init() { this.registerDomainControls(); this.registerGlobalControls(); this.registerInfoButton(); this.registerMasterSwitch(); } static registerMasterSwitch() { const allEnabled = Object.keys(CONFIG.defaultSettings).every( key => DomainConfig.getConfig(key) ); GM_registerMenuCommand( `🔘 一键${allEnabled ? '禁用' : '启用'}所有模块`, () => this.toggleAllModules() ); } static toggleAllModules() { const allKeys = Object.keys(CONFIG.defaultSettings); const currentState = allKeys.every(key => DomainConfig.getConfig(key)); allKeys.forEach(key => { DomainConfig.updateConfig(key, !currentState); }); GM_notification({ title: '总开关已切换', text: `所有模块已${!currentState ? '启用' : '禁用'}`, timeout: 2000 }); window.location.reload(); } static registerInfoButton() { GM_registerMenuCommand('📘 13模块说明', () => this.showInstructions()); } static showInstructions() { const instructions = `【广告终结者v1.3 - 13大模块说明】 ██ 核心拦截系统 ██ 1. 第三方资源拦截 ✔ 拦截规则: - 非本站域名的<script>/<iframe> - 排除白名单中的CDN资源 - 自动识别跟踪脚本 2. iframe属性检测 ✔ 拦截规则: - 尺寸<2x2像素的隐藏框架 - src包含50+广告关键词 - 移除iframe及父容器 3. 父容器检测 ✔ 拦截规则: - 包裹iframe的div/section - 无有效内容的空容器 - 多层嵌套广告容器 ██ 动态检测系统 ██ 4. 动态ID检测 ✔ 拦截规则: - ID长度>10字符 - 包含5+连续数字 - 示例:ad_12345 5. 属性相似度 ✔ 拦截规则: - ID与class相似度>80% - 属性值重复率过高 - 示例:id="ad" class="ad-box" 6. 尺寸异常 ✔ 拦截规则: - 元素面积>屏幕15% - 自动计算视窗占比 - 响应式布局识别 7. 广告属性检测 ✔ 拦截规则: - 12个属性关键词匹配 - 50+中英文广告词库 - 支持data-*属性 ██ 堆叠拦截系统 ██ 8. 高z-index检测 ✔ 拦截规则: - z-index值>50 - 排除导航菜单等白名单 - 动态堆叠上下文分析 9. 固定定位检测 ✔ 拦截规则: - fixed元素>2个 - 识别"回到顶部"等正常元素 - 支持sticky定位 10. 遮罩层检测 ✔ 拦截规则: - 半透明背景(rgba) - 覆盖80%屏幕宽度 - 防点击劫持 11. 浮动层检测 ✔ 拦截规则: - 边缘吸附<10px - 含float/sticky定位 - 30+中文特征词 ██ 增强功能模块 ██ 12. 嵌套框架检测 ✔ 拦截规则: - iframe嵌套>3层 - 空白嵌套框架 - 跨域嵌套容器 13. 文本广告检测 ✔ 拦截规则: - 包含20+营销关键词 - 无子元素的纯文本 - 微信号/QQ号识别`; alert(instructions); } static registerDomainControls() { const SEPARATOR = '───────────────'; GM_registerMenuCommand(SEPARATOR, () => {}); this.registerModuleControls([ 'thirdpartyCheck', 'dynamicIdDetection', 'attributeSimilarity', 'sizeAnomaly', 'adAttributeDetection' ]); GM_registerMenuCommand(SEPARATOR, () => {}); this.registerModuleControls([ 'iframeAttributeCheck', 'parentContainerCheck', 'nestedFrameDetection' ]); GM_registerMenuCommand(SEPARATOR, () => {}); this.registerModuleControls([ 'highZIndexDetection', 'fixedPositionCheck', 'overlayDetection', 'floatingLayerCheck' ]); GM_registerMenuCommand(SEPARATOR, () => {}); this.registerModuleControls([ 'floatingAdDetection', 'imageAdDetection', 'sidebarAdDetection', 'textAdDetection', 'cookieSyncDetection' ]); GM_registerMenuCommand(SEPARATOR, () => {}); GM_registerMenuCommand('🔄 重置当前网站设置', () => { DomainConfig.resetConfig(); GM_notification({ title: '配置已重置', text: `${DomainConfig.currentDomain} 设置已恢复默认`, timeout: 2000 }); window.location.reload(); }); } static registerModuleControls(keys) { keys.forEach(key => { const currentValue = DomainConfig.getConfig(key); GM_registerMenuCommand( ` ${this.getKeyName(key)} [${currentValue ? '✅' : '❌'}]`, () => this.toggleConfig(key) ); }); } static registerGlobalControls() { GM_registerMenuCommand('📜 查看拦截日志', this.showLogs.bind(this)); GM_registerMenuCommand('🧹 清除当前日志', this.clearLogs.bind(this)); } static toggleConfig(key) { const current = DomainConfig.getConfig(key); DomainConfig.updateConfig(key, !current); GM_notification({ title: '配置已更新', text: `${this.getKeyName(key)} 已${!current ? '启用' : '禁用'}`, timeout: 1500 }); window.location.reload(); } static getKeyName(key) { const names = { thirdpartyCheck: '第三方拦截', dynamicIdDetection: '动态ID检测', attributeSimilarity: '属性相似度', sizeAnomaly: '尺寸异常', adAttributeDetection: '广告属性检测', iframeAttributeCheck: 'iframe属性', parentContainerCheck: '父容器检测', nestedFrameDetection: '嵌套框架检测', highZIndexDetection: '高z-index', fixedPositionCheck: '固定定位', overlayDetection: '遮罩层检测', floatingLayerCheck: '浮动层检测', floatingAdDetection: '浮动广告检测', imageAdDetection: '图片广告检测', sidebarAdDetection: '侧边栏检测', textAdDetection: '文本广告检测', cookieSyncDetection: 'Cookie同步检测' }; return names[key] || key; } static showLogs() { const logs = Logger.getDomainLogs(); alert(logs.length ? `【${DomainConfig.currentDomain}】拦截记录:\n\n${Logger.formatLogs(logs)}` : '当前无拦截记录'); } static clearLogs() { Logger.clearDomainLogs(); GM_notification({title: '日志已清除', timeout: 1500}); } } // ======================= 日志系统 ======================= class Logger { static logRemoval(record) { const allLogs = GM_getValue('removalLogs', {}); const domainLogs = allLogs[DomainConfig.currentDomain] || []; domainLogs.push({ timestamp: new Date().toLocaleString(), ...record }); if (domainLogs.length > CONFIG.maxLogs) domainLogs.shift(); allLogs[DomainConfig.currentDomain] = domainLogs; GM_setValue('removalLogs', allLogs); } static getDomainLogs() { const allLogs = GM_getValue('removalLogs', {}); return allLogs[DomainConfig.currentDomain] || []; } static clearDomainLogs() { const allLogs = GM_getValue('removalLogs', {}); delete allLogs[DomainConfig.currentDomain]; GM_setValue('removalLogs', allLogs); } static formatLogs(logs) { return logs.map((log, index) => `[${index + 1}] ${log.timestamp}\n模块: ${log.module}\n` + `类型: ${log.reason.type}\n详情: ${log.reason.detail || ''}` ).join('\n\n'); } } // ======================= 系统初始化 ======================= let coreCleaner; function initialize() { if (coreCleaner) coreCleaner.destructor(); coreCleaner = new CoreCleaner(); } initialize(); UIController.init(); // CSS防护规则 const antiRevertStyle = document.createElement('style'); antiRevertStyle.textContent = ` html::-webkit-scrollbar { width: 0 !important } [style*="overflow:hidden"] { overflow: visible !important } [data-ad-container] { display: none !important } `; document.head.appendChild(antiRevertStyle); })();