// ==UserScript== // @name 广告过滤助手 - 插播/跑马灯/水印 // @namespace https://example.com // @version 1.0.0 // @description 过滤网页插播广告、去除跑马灯广告、移除左右下角水印广告 // @author You // @match *://*/* // @grant none // @run-at document-start // @noframes // ==/UserScript== (function() { 'use strict'; // 常见广告容器选择器 const AD_SELECTORS = [ // 插播广告 '[class*="popup"]', '[class*="popup-ad"]', '[class*="modal"][class*="ad"]', '[id*="popup"]', '[id*="popup-ad"]', '.ad-popup', '.popup-modal', '.modal-overlay[class*="ad"]', // 跑马灯广告 '[class*="marquee"]', '[class*="scroll-ad"]', '[class*="slider-ad"]', '[class*="banner-scroll"]', '[class*="ticker"]', '.marquee-container', '.news-ticker', '.ad-ticker', // 左右下角水印广告 '[class*="corner-ad"]', '[class*="side-ad"]', '[class*="float-ad"]', '[class*="fixed-ad"]', '[class*="sticky-ad"]', '[class*="bottom-ad"]', '[class*="left-ad"]', '[class*="right-ad"]', '[class*="watermark"]', '.left-banner', '.right-banner', '.left-sidebar-ad', '.right-sidebar-ad', '.bottom-right-ad', '.bottom-left-ad', '.corner-banner', '[style*="position: fixed"][style*="bottom"]', '[style*="position: fixed"][style*="left"]', '[style*="position: fixed"][style*="right"]', // 通用广告类名 '[class*="ads-"]', '[class*="-ads"]', '[class*="advert"]', '[class*="sponsor"]', '[id*="ads-"]', '[id*="-ad-"]', '[id*="advert"]', // 悬浮广告 '.float-layer', '.suspension-ad', '.suspension-box' ]; // 广告关键词(用于识别) const AD_KEYWORDS = [ '广告', 'ad-', 'ads-', 'advert', 'sponsor', '推广', '招商', '投放', '合作', 'popup', 'modal', 'overlay', 'banner', 'float', 'fixed' ]; // 需要排除的非广告元素 const EXCLUDE_SELECTORS = [ 'nav', 'header', 'footer', 'main', 'article', '[role="navigation"]', '[role="banner"]', '[role="main"]', '.navigation', '.nav-menu', '.menu', '#header', '#footer', '#main', '#nav' ]; /** * 判断元素是否是广告 */ function isAdElement(el) { if (!el) return false; // 检查是否在排除列表中 for (const selector of EXCLUDE_SELECTORS) { if (el.matches && el.matches(selector)) { return false; } } const className = el.className || ''; const id = el.id || ''; const tagName = el.tagName || ''; // 检查标签名 if (['SCRIPT', 'STYLE', 'META', 'LINK', 'NOSCRIPT'].includes(tagName)) { return false; } // 检查 className 和 id const textToCheck = className + ' ' + id; for (const keyword of AD_KEYWORDS) { if (textToCheck.toLowerCase().includes(keyword.toLowerCase())) { // 额外验证:确保是广告容器而非正常内容 if (el.textContent && el.textContent.trim().length < 200) { return true; } } } // 检查子元素是否包含广告 const children = el.querySelectorAll ? el.querySelectorAll('*') : []; if (children.length > 0) { let adChildrenCount = 0; for (const child of children) { const childClass = child.className || ''; const childId = child.id || ''; const childText = childClass + ' ' + childId; for (const keyword of AD_KEYWORDS) { if (childText.toLowerCase().includes(keyword.toLowerCase())) { adChildrenCount++; break; } } } // 如果子元素中超过30%是广告元素,认为当前也是广告容器 if (children.length > 0 && adChildrenCount / children.length > 0.3) { return true; } } return false; } /** * 隐藏广告元素 */ function hideAdElement(el) { if (el && el.style) { el.style.display = 'none'; el.style.visibility = 'hidden'; el.style.opacity = '0'; el.style.pointerEvents = 'none'; el.setAttribute('data-ad-hidden', 'true'); } } /** * 移除广告元素 */ function removeAdElement(el) { if (el && el.parentNode) { el.parentNode.removeChild(el); return true; } return false; } /** * 使用选择器移除广告 */ function removeAdsBySelectors() { for (const selector of AD_SELECTORS) { try { const elements = document.querySelectorAll(selector); for (const el of elements) { if (isAdElement(el)) { removeAdElement(el); } } } catch (e) { // 忽略无效选择器 } } } /** * 移除插播广告(弹窗类) */ function removePopupAds() { // 查找全屏遮罩 const overlays = document.querySelectorAll('[class*="overlay"], [class*="mask"]'); for (const overlay of overlays) { if (overlay.clientWidth > window.innerWidth * 0.5 || overlay.clientHeight > window.innerHeight * 0.5) { const parent = overlay.parentElement; if (parent && isAdElement(parent)) { removeAdElement(parent); } } } // 查找模态框广告 const modals = document.querySelectorAll('[class*="modal"]:not([class*="nav"]):not([class*="menu"])'); for (const modal of modals) { if (isAdElement(modal)) { removeAdElement(modal); } } } /** * 移除跑马灯/滚动广告 */ function removeMarqueeAds() { // 查找 marquee 元素 const marquees = document.querySelectorAll('marquee'); for (const marquee of marquees) { hideAdElement(marquee); } // 查找滚动容器 const scrollContainers = document.querySelectorAll('[class*="scroll"], [class*="ticker"], [class*="marquee"]'); for (const container of scrollContainers) { if (isAdElement(container) || container.textContent.length < 300) { hideAdElement(container); } } } /** * 移除角落水印广告 */ function removeCornerWatermarkAds() { // 查找固定定位的角落元素 const allElements = document.querySelectorAll('*'); for (const el of allElements) { const style = window.getComputedStyle(el); const position = style.position; if (position === 'fixed' || position === 'absolute') { const rect = el.getBoundingClientRect(); // 检查是否是角落位置 const isInCorner = ( (rect.top < 100 || rect.bottom > window.innerHeight - 100) && (rect.left < 100 || rect.right > window.innerWidth - 100) ); // 检查是否是较小的悬浮块 const isSmallBlock = rect.width < 300 && rect.height < 300; if (isInCorner && isSmallBlock) { if (isAdElement(el)) { hideAdElement(el); } } } } // 特定角落广告类名 const cornerSelectors = [ '.left-banner', '.right-banner', '.bottom-left-banner', '.bottom-right-banner', '.corner-banner', '.side-banner', '[class*="corner"][class*="ad"]', '[class*="side"][class*="ad"]' ]; for (const selector of cornerSelectors) { try { const elements = document.querySelectorAll(selector); for (const el of elements) { hideAdElement(el); } } catch (e) { // 忽略 } } } /** * 主动防御:观察新增元素 */ function observeNewElements() { const observer = new MutationObserver((mutations) => { let shouldClean = false; for (const mutation of mutations) { if (mutation.addedNodes.length > 0) { shouldClean = true; break; } } if (shouldClean) { requestAnimationFrame(() => { removeAdsBySelectors(); removePopupAds(); removeMarqueeAds(); }); } }); observer.observe(document.documentElement, { childList: true, subtree: true }); } /** * 主执行函数 */ function main() { // 立即执行一次清理 removeAdsBySelectors(); removePopupAds(); removeMarqueeAds(); removeCornerWatermarkAds(); // 启动观察器 observeNewElements(); // 定期检查(作为备份) setInterval(() => { removeCornerWatermarkAds(); }, 5000); } // 在文档开始时执行 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', main); } else { main(); } // 页面可见性变化时重新检查 document.addEventListener('visibilitychange', () => { if (!document.hidden) { setTimeout(() => { removeAdsBySelectors(); removeCornerWatermarkAds(); }, 100); } }); })();