【油猴脚本】微博广告与推荐内容屏蔽工具
https://www.52pojie.cn/thread-2057844-1-1.html
(出处: 吾爱破解论坛)
- // ==UserScript==// @name 微博广告与推荐内容屏蔽工具(优化版)// @namespace [url=http://tampermonkey.net/]http://tampermonkey.net/[/url]// @version 2.0// @description 高性能屏蔽微博广告、推荐内容及侧栏推荐,支持配置和调试// @author Chief Programmer// @match [url=https://weibo.com/]https://weibo.com/[/url]*// @match https://*.weibo.com/*// [url=home.php?mod=space&uid=111117]@icon[/url] [url=https://weibo.com/favicon.ico]https://weibo.com/favicon.ico[/url]// @grant GM_addStyle// @grant GM_getValue// @grant GM_setValue// @grant GM_registerMenuCommand// @license MIT// ==/UserScript==(function() { \\\'use strict\\\'; // ================== 配置管理 ================== const CONFIG = { // 功能开关 blockAds: GM_getValue(\\\'blockAds\\\', true), blockSidebar: GM_getValue(\\\'blockSidebar\\\', true), blockImages: GM_getValue(\\\'blockImages\\\', true), debugMode: GM_getValue(\\\'debugMode\\\', false), // 屏蔽关键词(可扩展) blockKeywords: GM_getValue(\\\'blockKeywords\\\', [\\\'荐读\\\', \\\'推荐\\\', \\\'公益\\\', \\\'广告\\\']), // 性能配置 observerDelay: 50, // MutationObserver 延迟(ms) scrollThrottle: 200, // 滚动节流时间(ms) batchSize: 10, // 批处理大小 // 选择器配置(便于维护) selectors: { feedItem: \\\'article.Feed_wrap_3v9LH.Feed_normal_12A98\\\', tagContainer: \\\'.wbpro-tag-c2 div\\\', sidebarTitle: \\\'div.wbpro-side-tit .f16.fm.cla\\\', sidebarParent: \\\'.wbpro-side\\\' } }; // ================== 工具函数 ================== /** * 节流函数 */ function throttle(func, limit) { let inThrottle; return function(...args) { if (!inThrottle) { func.apply(this, args); inThrottle = true; setTimeout(() => inThrottle = false, limit); } }; } /** * 防抖函数 */ function debounce(func, delay) { let timeoutId; return function(...args) { clearTimeout(timeoutId); timeoutId = setTimeout(() => func.apply(this, args), delay); }; } /** * 日志输出(支持调试模式) */ function log(message, type = \\\'info\\\', data = null) { if (!CONFIG.debugMode && type !== \\\'error\\\') return; const prefix = \\\'【微博内容屏蔽 v2.0】\\\'; const timestamp = new Date().toLocaleTimeString(); switch(type) { case \\\'error\\\': console.error(`${prefix}[${timestamp}]`, message, data || \\\'\\\'); break; case \\\'warn\\\': console.warn(`${prefix}[${timestamp}]`, message, data || \\\'\\\'); break; case \\\'success\\\': console.log(`%c${prefix}[${timestamp}] ${message}`, \\\'color: green\\\', data || \\\'\\\'); break; default: console.log(`${prefix}[${timestamp}]`, message, data || \\\'\\\'); } } /** * 性能监控 */ const performanceMonitor = { stats: { blockedItems: 0, blockedImages: 0, blockedSidebars: 0, executionTime: 0 }, start() { return performance.now(); }, end(startTime, operation) { const duration = performance.now() - startTime; this.stats.executionTime += duration; if (CONFIG.debugMode) { log(`${operation} 耗时: ${duration.toFixed(2)}ms`, \\\'info\\\'); } }, report() { log(\\\'性能统计\\\', \\\'success\\\', this.stats); } }; // ================== 核心功能 ================== /** * 注入优化的CSS样式 */ function injectStyles() { const styles = ` /* 屏蔽推荐图片 - 使用更精确的选择器 */ ${CONFIG.blockImages ? ` img[src*=\"shuakong.jpg\"], img[src*=\"upload/1014/739/2023/08/03/shuakong.jpg\"] { display: none !important; visibility: hidden !important; opacity: 0 !important; width: 0 !important; height: 0 !important; } ` : \\\'\\\'} /* 隐藏标记的广告容器 - 添加平滑过渡 */ .weibo-ad-blocked { display: none !important; opacity: 0 !important; transition: opacity 0.3s ease-out; pointer-events: none !important; } /* 调试模式高亮 */ ${CONFIG.debugMode ? ` .weibo-ad-blocked { display: block !important; opacity: 0.3 !important; border: 2px dashed red !important; background: rgba(255,0,0,0.1) !important; } ` : \\\'\\\'} `; GM_addStyle(styles); log(\\\'样式注入成功\\\', \\\'success\\\'); } /** * 批量处理信息流广告 */ function processFeedItems() { if (!CONFIG.blockAds) return; const startTime = performanceMonitor.start(); const feedItems = document.querySelectorAll( `${CONFIG.selectors.feedItem}:not([data-processed=\"true\"])` ); let blockedCount = 0; const itemsToProcess = Array.from(feedItems).slice(0, CONFIG.batchSize); itemsToProcess.forEach(container => { try { // 标记为已处理 container.setAttribute(\\\'data-processed\\\', \\\'true\\\'); const tagElement = container.querySelector(CONFIG.selectors.tagContainer); if (!tagElement) return; const text = tagElement.textContent.trim(); const shouldBlock = CONFIG.blockKeywords.some(keyword => text.includes(keyword) ); if (shouldBlock) { container.classList.add(\\\'weibo-ad-blocked\\\'); blockedCount++; performanceMonitor.stats.blockedItems++; log(`屏蔽信息流: \"${text}\"`, \\\'success\\\'); } } catch (error) { log(\\\'处理信息流条目时出错\\\', \\\'error\\\', error); } }); if (blockedCount > 0) { log(`本次屏蔽 ${blockedCount} 条内容`, \\\'info\\\'); } performanceMonitor.end(startTime, \\\'处理信息流\\\'); // 如果还有未处理的元素,继续处理 if (feedItems.length > CONFIG.batchSize) { setTimeout(() => processFeedItems(), 50); } } /** * 屏蔽侧栏推荐(优化版) */ function hideSidebarRecommendations() { if (!CONFIG.blockSidebar) return; const startTime = performanceMonitor.start(); try { // 使用更高效的查询方式 const sidebars = document.querySelectorAll( `${CONFIG.selectors.sidebarParent}:not([data-sidebar-processed=\"true\"])` ); sidebars.forEach(sidebar => { const title = sidebar.querySelector(CONFIG.selectors.sidebarTitle); if (title && title.textContent.trim() === \\\'你可能感兴趣的人\\\') { sidebar.style.display = \\\'none\\\'; sidebar.setAttribute(\\\'data-sidebar-processed\\\', \\\'true\\\'); performanceMonitor.stats.blockedSidebars++; log(\\\'屏蔽侧栏推荐\\\', \\\'success\\\'); } }); } catch (error) { log(\\\'处理侧栏推荐时出错\\\', \\\'error\\\', error); } performanceMonitor.end(startTime, \\\'处理侧栏\\\'); } /** * 主处理函数(防抖优化) */ const processContent = debounce(() => { processFeedItems(); hideSidebarRecommendations(); }, CONFIG.observerDelay); // ================== 初始化 ================== /** * 设置 MutationObserver(优化版) */ function setupObserver() { let pendingMutations = []; let rafId = null; const processMutations = () => { if (pendingMutations.length > 0) { processContent(); pendingMutations = []; } rafId = null; }; const observer = new MutationObserver((mutations) => { // 过滤无关的变化 const relevantMutations = mutations.filter(mutation => { // 忽略属性变化和我们自己的修改 if (mutation.type === \\\'attributes\\\' && mutation.attributeName === \\\'data-processed\\\') { return false; } // 忽略文本节点变化 if (mutation.type === \\\'characterData\\\') { return false; } return true; }); if (relevantMutations.length > 0) { pendingMutations.push(...relevantMutations); // 使用 requestAnimationFrame 优化 if (!rafId) { rafId = requestAnimationFrame(processMutations); } } }); observer.observe(document.body, { childList: true, subtree: true, attributes: false, // 减少不必要的属性监听 characterData: false }); log(\\\'DOM 监听器已启动\\\', \\\'success\\\'); return observer; } /** * 设置滚动监听(节流优化) */ function setupScrollListener() { const throttledProcess = throttle(() => { processContent(); }, CONFIG.scrollThrottle); window.addEventListener(\\\'scroll\\\', throttledProcess, { passive: true }); log(\\\'滚动监听器已启动\\\', \\\'success\\\'); } /** * 注册用户菜单命令 */ function setupMenuCommands() { GM_registerMenuCommand(\\\'切换调试模式\\\', () => { CONFIG.debugMode = !CONFIG.debugMode; GM_setValue(\\\'debugMode\\\', CONFIG.debugMode); alert(`调试模式已${CONFIG.debugMode ? \\\'开启\\\' : \\\'关闭\\\'}`); location.reload(); }); GM_registerMenuCommand(\\\'查看统计信息\\\', () => { performanceMonitor.report(); alert(`已屏蔽内容统计:\\\\n` + `- 信息流条目: ${performanceMonitor.stats.blockedItems}\\\\n` + `- 侧栏推荐: ${performanceMonitor.stats.blockedSidebars}\\\\n` + `- 总执行时间: ${performanceMonitor.stats.executionTime.toFixed(2)}ms`); }); GM_registerMenuCommand(\\\'配置屏蔽关键词\\\', () => { const currentKeywords = CONFIG.blockKeywords.join(\\\',\\\'); const newKeywords = prompt(\\\'请输入屏蔽关键词(逗号分隔):\\\', currentKeywords); if (newKeywords !== null) { CONFIG.blockKeywords = newKeywords.split(\\\',\\\').map(k => k.trim()); GM_setValue(\\\'blockKeywords\\\', CONFIG.blockKeywords); alert(\\\'关键词已更新,页面将重新加载\\\'); location.reload(); } }); } /** * 初始化函数 */ function init() { try { log(\\\'开始初始化...\\\', \\\'info\\\'); // 1. 注入样式 injectStyles(); // 2. 初始处理 setTimeout(() => { processContent(); }, 500); // 3. 设置监听器 setupObserver(); setupScrollListener(); // 4. 注册菜单 setupMenuCommands(); // 5. 页面可见性变化时处理 document.addEventListener(\\\'visibilitychange\\\', () => { if (!document.hidden) { processContent(); } }); log(\\\'初始化完成!\\\', \\\'success\\\'); // 定期报告(调试模式) if (CONFIG.debugMode) { setInterval(() => { performanceMonitor.report(); }, 30000); } } catch (error) { log(\\\'初始化失败\\\', \\\'error\\\', error); } } // ================== 启动脚本 ================== if (document.readyState === \\\'loading\\\') { document.addEventListener(\\\'DOMContentLoaded\\\', init); } else { init(); }})();
复制代码 |