如何定位并阻止触发网站烦人的随机弹窗的JavaScript函数?
排查并阻止网站随机弹窗的方法
问题背景
网站每隔x分钟随机弹出带随机CSS ID的div弹窗,通过Chrome开发者工具的break on subtree modifications发现弹窗调用了jquery-2.0.3.min.js中的insertBefore和removeChild函数,相关代码如下:
before: function() { return this.domManip(arguments, function(e) { this.parentNode && this.parentNode.insertBefore(e, this) }) }, after: function() { return this.domManip(arguments, function(e) { this.parentNode && this.parentNode.insertBefore(e, this.nextSibling) }) }, remove: function(e, t) { var n, r = e ? x.filter(e, this) : this, i = 0; for (; null != (n = r[i]); i++) t || 1 !== n.nodeType || x.cleanData(mt(n)), n.parentNode && (t && x.contains(n.ownerDocument, n) && dt(mt(n, "script")), n.parentNode.removeChild(n)); return this },
弹窗显示一分钟后自动消失,未发现特定触发事件,希望通过Greasemonkey类工具实现阻止。
进一步排查方法
- 追踪弹窗DOM固定特征:弹窗出现时右键检查元素,除随机ID外,留意是否有固定class名、父容器标识、弹窗内固定文本/结构(比如固定样式的关闭按钮),这些特征能帮你精准定位弹窗,不用依赖随机ID。
- 定位定时触发任务:用Chrome开发者工具
Sources面板查看Global listeners里的setTimeout/setInterval事件,或在控制台执行console.log(setTimeout)追踪所有定时任务,找到对应弹窗触发的定时器ID。 - Hook方法溯源触发代码:在控制台临时重写
insertBefore方法,打印调用栈找到弹窗创建的源头:
const originalInsertBefore = Element.prototype.insertBefore; Element.prototype.insertBefore = function() { // 替换为你观察到的弹窗特征 if (arguments[0].tagName === 'DIV' && arguments[0].style.position === 'fixed') { console.trace('弹窗插入触发'); } return originalInsertBefore.apply(this, arguments); };
用Greasemonkey/Tampermonkey阻止弹窗的方案
方案1:DOM变化实时拦截
基于找到的弹窗固定特征,用MutationObserver监听DOM,发现弹窗直接移除:
// ==UserScript== // @name 阻止网站随机弹窗 // @namespace http://tampermonkey.net/ // @version 0.1 // @description 拦截定时弹出的随机ID弹窗 // @author You // @match 目标网站的URL // @grant none // ==/UserScript== (function() { 'use strict'; // 自定义弹窗识别逻辑,替换为实际特征 const isPopup = (element) => { return element.tagName === 'DIV' && element.style.position === 'fixed' && element.innerHTML.includes('弹窗内固定文本'); }; const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { mutation.addedNodes.forEach((node) => { if (node.nodeType === 1 && isPopup(node)) { node.remove(); console.log('已拦截弹窗'); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })();
方案2:Hook jQuery操作方法
针对弹窗使用的jQuery方法,重写后阻止弹窗插入:
// ==UserScript== // @name 阻止网站随机弹窗 // @namespace http://tampermonkey.net/ // @version 0.1 // @description 通过Hook jQuery方法拦截弹窗 // @author You // @match 目标网站的URL // @grant none // ==/UserScript== (function() { 'use strict'; const waitForJQuery = setInterval(() => { if (window.jQuery) { clearInterval(waitForJQuery); // Hook before方法 const originalBefore = jQuery.fn.before; jQuery.fn.before = function() { const elements = Array.from(arguments).flat().filter(el => el.nodeType === 1); const hasPopup = elements.some(el => el.tagName === 'DIV' && el.style.position === 'fixed'); if (hasPopup) { console.log('拦截弹窗插入'); return this; } return originalBefore.apply(this, arguments); }; // 同理可Hook after、append等方法 const originalAfter = jQuery.fn.after; jQuery.fn.after = function() { const elements = Array.from(arguments).flat().filter(el => el.nodeType === 1); const hasPopup = elements.some(el => el.tagName === 'DIV' && el.style.position === 'fixed'); if (hasPopup) { console.log('拦截弹窗插入'); return this; } return originalAfter.apply(this, arguments); }; } }, 100); })();
方案3:清除触发定时器
若找到弹窗对应的定时器ID,直接清除定时任务:
// ==UserScript== // @name 阻止网站随机弹窗 // @namespace http://tampermonkey.net/ // @version 0.1 // @description 清除弹窗的定时触发任务 // @author You // @match 目标网站的URL // @grant none // ==/UserScript== (function() { 'use strict'; const originalSetTimeout = window.setTimeout; window.setTimeout = function(callback, delay) { const timerId = originalSetTimeout(callback, delay); // 根据弹窗触发逻辑的特征判断 if (callback.toString().includes('createElement') && callback.toString().includes('fixed')) { console.log('清除弹窗定时器,ID:', timerId); clearTimeout(timerId); } return timerId; }; })();
内容的提问来源于stack exchange,提问作者Will
相关产品推荐
相关产品推荐

