// ==UserScript== // @name 屏蔽百度搜索百家号文章 // @website https://225336.xyz // @source https://github.com/tengxunlaozu/baijiahao // @namespace https://github.com/tengxunlaozu/baijiahao // @support https://github.com/tengxunlaozu/baijiahao/issues // @version 3.1 // @description 屏蔽百家号文章,保留百度天气/工具卡片,避免页面滚动位置跳回 // @author tengxunlaozu // @match *://www.baidu.com/* // ==/UserScript== (function () { 'use strict'; /* * 百度工具/功能卡片 * * 这些内容不能删除: * 天气、空气质量、时间、日期、节假日、 * 计算器、单位换算、汇率、翻译、词典、 * IP、WHOIS、地图、路线、公交等。 */ const TOOL_TPL_RE = /(^|_)(weather|air_quality|time_now|date_query|holiday|calculator|unit_convert|exchange_rate|translate|dict|ip_query|whois|map|route_plan|transit)(_|$)/i; const TOOL_NAME_RE = /(weather|air.?quality|calculator|translate|dict|map|unit|exchange|ip.?query|whois|route|transit)/i; const TOOL_URL_RE = /(weathernew\.pae\.baidu\.com|fanyi\.baidu\.com|dict\.baidu\.com|map\.baidu\.com)/i; /* * 判断是不是百度工具卡片 */ function isBaiduToolCard(el) { if (!el || el.nodeType !== 1) { return false; } const tpl = el.getAttribute('tpl') || ''; if (TOOL_TPL_RE.test(tpl)) { return true; } const mName = el.getAttribute('m-name') || ''; if (TOOL_NAME_RE.test(mName)) { return true; } const mu = el.getAttribute('mu') || ''; if (TOOL_URL_RE.test(mu)) { return true; } /* * 新版百度有些工具卡没有 tpl / m-name / mu, * 从 class、id、data 属性中辅助判断。 */ const hint = [ el.id || '', typeof el.className === 'string' ? el.className : '', el.getAttribute('data-component') || '', el.getAttribute('data-module') || '' ].join(' '); return /weather|forecast|air.?quality|calculator/i.test(hint); } /* * 获取百度搜索结果的外层容器 */ function getResultContainer(el) { if (!el) { return null; } return el.closest('.result, .c-container'); } /* * 判断一个搜索结果是不是百家号 * * 只有明确确认是百家号才删除。 * * 不再因为 class="cosc-card" 就直接删除。 */ function isBaijiahaoContainer(container) { if (!container) { return false; } /* * 百度工具卡绝对不能删除 */ if (isBaiduToolCard(container)) { return false; } /* * 1. 最可靠:mu 属性 */ const mu = container.getAttribute('mu') || ''; if (/baijiahao\.baidu\.com/i.test(mu)) { return true; } /* * 2. data-click-info * * nohumanReview 是百度百家号结果经常使用的标记。 */ const infoElement = container.querySelector('[data-click-info]'); const info = infoElement?.getAttribute('data-click-info') || ''; if (/nohumanReview/i.test(info)) { return true; } /* * 3. 检查容器内部链接 */ const links = container.querySelectorAll('a[href], [mu]'); for (const node of links) { const href = node.getAttribute('href') || ''; const nodeMu = node.getAttribute('mu') || ''; if ( /baijiahao\.baidu\.com/i.test(href) || /baijiahao\.baidu\.com/i.test(nodeMu) ) { return true; } } return false; } /* * 删除结果 */ function removeContainer(container) { if (!container) { return; } if ( container === document.body || container === document.documentElement ) { return; } container.remove(); } /* * 删除百家号 */ function killBaijiahao() { /* * 1. * * 通过 mu 判断百家号。 * * 注意: * 不再使用: * * .cosc-card * * 作为删除条件。 */ document .querySelectorAll( '.result.c-container[mu], .c-container[mu], .result[mu]' ) .forEach(container => { if (isBaijiahaoContainer(container)) { removeContainer(container); } }); /* * 2. * * nohumanReview */ document .querySelectorAll( '[data-click-info*="nohumanReview"]' ) .forEach(el => { const container = getResultContainer(el); if ( container && !isBaiduToolCard(container) && isBaijiahaoContainer(container) ) { removeContainer(container); } }); /* * 3. * * 新版 cosc-card * * 只删除明确确认属于百家号的卡片。 * * 不再直接: * * el.remove() */ document .querySelectorAll('.cosc-card') .forEach(card => { if (isBaiduToolCard(card)) { return; } if (isBaijiahaoContainer(card)) { removeContainer(card); } }); /* * 4. * * 百度跳转链接兜底 */ document .querySelectorAll( 'a[href^="https://www.baidu.com/link"]' ) .forEach(a => { const container = getResultContainer(a); if ( container && !isBaiduToolCard(container) && isBaijiahaoContainer(container) ) { removeContainer(container); } }); /* * 5. * * aladdin 聚合卡 * * 同样必须确认 mu 是百家号。 */ document .querySelectorAll( '[class*="aladdin"], [class*="aladding"]' ) .forEach(el => { const container = getResultContainer(el); if ( container && !isBaiduToolCard(container) && isBaijiahaoContainer(container) ) { removeContainer(container); } }); } /* * -------------------------------------------------- * MutationObserver 优化 * -------------------------------------------------- * * 百度搜索页面会频繁修改 DOM。 * * 以前是: * * DOM变化 * ↓ * killBaijiahao() * ↓ * 大量 remove() * * 容易导致滚动位置异常。 * * 现在改成 requestAnimationFrame 合并处理。 */ let scheduled = false; function scheduleCleanup() { if (scheduled) { return; } scheduled = true; requestAnimationFrame(() => { scheduled = false; killBaijiahao(); }); } /* * 首次执行 */ if (document.body) { scheduleCleanup(); } else { document.addEventListener( 'DOMContentLoaded', scheduleCleanup, { once: true } ); } /* * 监听百度动态加载内容 */ const observer = new MutationObserver(scheduleCleanup); observer.observe( document.documentElement, { childList: true, subtree: true } ); })();