屏蔽网址弹出框和复制拦截

1,510 阅读3分钟

1.起因

​ 查询资料,国内媒体往往为了增加用户注册,再查询浏览相关网站时往往增加弹窗口手动关闭或者登陆账号后才不会弹出(某乎更是不断弹出),对于这种弹窗实在影响体验(搬砖速度)。 ​

2.工具Custom JavaScript for websites

​ chrome 扩展插件(fireFox 也有相应的插件),对于不同网址使用自定义用户代码,打开插件后如图,直接插入需要执行的 js 代码,再点击保存即可 ​ ​

3.解决

思路一:处理 fixed 定位元素

​ 大多数弹窗为 fixed 定位元素,找到所有 position 为 fixed 的元素,然后修改元素的 display 为 none 从而覆盖 class 的 display 属性,实现隐藏元素

const divArry = Array.prototype.slice.call(document.querySelectorAll('div'));
const fixedArray = divArry.filter(item => item.style.position == 'fixed'); // 杀伤力太大
fixedArray.map(item => item.style.position = 'static');

缺点:

  1. 范围太大,可能会影响部分非弹窗元素正常显示

  2. 无法处理动态添加的元素

思路二:弹窗元素处理

​ 通过选择器找到弹窗元素(缩小范围),进行删除弹窗结点或者修改弹窗结点样式,进而实现隐藏弹窗

const selectors = ['.modal'];
selectors.map(item => document.querySelector(item) && document.querySelector(item).remove()); // 删除或者改样式

缺点:

  1. 虽然范围缩小,但是依旧无法处理动态添加的元素

思路三:污染 css

​ 找到弹窗关键选择器进行污染,外部引入 css 无法修改,但是添加 style 标签进行污染(只有魔法才能打败魔法)

const cssText ='.modal { display:none !important}';
const style = document.createElement('style');
style.type = 'text/css';
const textNode = document.createTextNode(cssText);
style.appendChild(textNode);
document.head.appendChild(style);

缺点:

  1. 如果元素没有任何的class、id等,全部使用style并且display、visibility、opacity、z-Index、tansform全部!important写死(是个狼人),这种情况无法达到污染效果

思路四:删除最后一个子元素

​ 多数弹窗为了实现遮盖其他层元素,大多脱离当前文档流,通过监听滚动事件,js动态添加body的子元素。我们可以通过监听滚动事件或者定时器,对document.body子元素的tagName进行比较(保险起见对1/2以后的结点进行判断),如果非SCRIPT执行删除操作。

// 定时器或者监听滚动事件
(function () {
  const timer = setInterval(() => {
    const children = Array.prototype.slice.call(
      document.body.children,
      Math.floor(document.body.children.length / 2)
    );
    children.map((node) => node.tagName != "SCRIPT" && node.remove());
  }, 1000);
})();

缺点:

  1. 监听或者定时有性能消耗,实时性没有这么高,如果弹窗非登录这种会误杀。

后续

还有部分网站增加了复制检测(某gmentfault点名批评,技术用来作恶),严重影响复制代码效率。更为过分的是关键事件使用原生js进行绑定匿名事件,这种基本上无法移除,但是chrome给我们开了小灶getEventListeners这个方法可以获取所有绑定事件包括匿名事件,然后再去执行移除事件即可

document.querySelectorAll("article.article")[1]
    .removeEventListener('copy',
    	// key point
    	getEventListeners(document.querySelectorAll("article.article")[1]).copy[0].listener
    )

4.总结

没有既不牺牲性能又可以处理动态添加结点的办法,鱼和熊掌不可兼得,同时部分网站还有锁定滚动轴等骚操作,还得执行额外代码,总是魔高一尺道高一丈,高手过招,只能见招拆招,针对特定网站设置特定的代码进行屏蔽。