应精准监听高危广告容器节点而非整个body,用querySelector定位data-ad-container等稳定属性;过滤addedNodes中非元素节点,用matches匹配广告特征并深入查询子节点;attributeFilter限定class/style/hidden,修复前断开observer,优先textContent清空或setAttribute标记移除。

监听广告节点插入的 MutationObserver 基础写法
直接监听 document.body 的子节点变动是最常用起点,但要注意:广告常通过 innerHTML、appendChild 或框架(如 React)的 createPortal 插入,这些操作都会触发 childList 类型的 mutation。必须开启 subtree: true,否则只监听 body 直接子元素,漏掉嵌套层级里的广告容器。
示例最小可用配置:
const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
mutation.addedNodes.forEach(node => {
if (node.nodeType === 1 && isAdNode(node)) {
node.remove();
}
// 还需遍历 node 的后代,因为广告可能作为子元素插入
if (node.nodeType === 1) {
node.querySelectorAll('*').forEach(el => {
if (isAdNode(el)) el.remove();
});
}
});
});
});
observer.observe(document.body, { childList: true, subtree: true });
判断广告节点的 isAdNode 函数怎么写才靠谱
靠 class 名(如 ad-banner、google-ad)或 id(如 ad-leaderboard)最直接,但容易被绕过;更稳定的是结合多个信号:
- 检查
node.className或node.id是否匹配常见广告关键词(注意大小写和连字符变体) - 检查
node.dataset是否含ad、advert等字段 - 检查
node.tagName是否为INS、AD(某些自定义标签)、或IFRAME且src含广告域名(如doubleclick.net、googlesyndication.com) - 避免仅用
textContent匹配“广告”二字——误杀率高,且现代广告多为图片/iframe
简单 isAdNode 示例:
使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。
立即学习“前端免费学习笔记(深入)”;
function isAdNode(el) {
const cls = el.className || '';
const id = el.id || '';
const tag = el.tagName;
const src = el.src || el.getAttribute('src') || '';
return (
/ad|advert|sponsor|taboola|outbrain/i.test(cls + id + tag) ||
(tag === 'IFRAME' && /doubleclick|googlesyndication|amazon-adsystem/i.test(src))
);
}
为什么广告删不干净?常见漏网场景和对策
广告脚本常在移除后几毫秒内重插,或使用 document.write、eval 动态生成,导致 MutationObserver 来不及响应。这时不能只依赖一次 remove():
- 对已移除的节点打标记(如设置
el.dataset.removed = 'true'),后续 mutation 中跳过已处理节点 - 监听
attributes变动,有些广告会动态改style.display或加hidden属性来“复活” - 对 iframe 广告,仅
remove()不够,要同时清空其src或调用contentWindow?.close()(受同源策略限制) - 某些 SPA 应用(React/Vue)用虚拟 DOM,真实 DOM 节点插入前已被 diff,此时需配合
requestIdleCallback延迟扫描,或监听document的readystatechange事件补漏
性能与兼容性要注意什么
MutationObserver 在低端设备上高频触发可能卡顿,尤其当广告频繁重绘时:
- 不要在
mutation.addedNodes循环里做复杂 DOM 查询(如document.querySelectorAll),改用node.querySelectorAll限定范围 - 避免在回调中修改被观察的 DOM(比如一边删广告一边又插入新节点),这会触发新一轮 observer,形成循环;确保
isAdNode判断和remove()是幂等的 - IE 不支持 MutationObserver,若需兼容,得 fallback 到
DOMSubtreeModified(已废弃,性能差)或轮询document.body.innerHTML(不推荐) - Chrome 扩展中可用
chrome.webRequest拦截广告资源,比 DOM 层面删除更彻底——但这不属于 MutationObserver 范畴了
真正难的不是监听和删除,而是对抗广告加载策略的迭代:它们会换 class 名、拆分 DOM 结构、延迟插入、甚至检测你是否在删广告。所以 isAdNode 的规则得持续更新,且最好留个开关让用户手动停用 observer,避免误伤内容。


















