同样的 DOM 操作为什么会有不一样的结果?

992 阅读4分钟

同样的 DOM 操作为什么会有不一样的结果?

「这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战」。

深夜光顾小网站,一进去竟然全部是广告,可惜 wuhen 模式下无法开启我的 Adblock,可我再转念一下,删广告这种事还用得着浏览器插件,不就是一个 DOM 操作?我直接一行代码删完(放抖音上又是堪比 python 画花的一个爆款小作品)

t_3.jpg

即使面对内容丰富的网站,我依然还是面不改色的简单的进行了一下页面分析,很快啊,我打开了开发者工具,我一个 ctrl + c 迅速定位到广告栏,然后一个右键 Copy selector,拿到选择器,然后所谓的一行代码就出现了(凭我这分析速度,明天又可以跟隔壁小梁吹我会爬虫了)

document.querySelector("#HMRichBox").remove();

很快啊,我在控制台上复制粘贴,一个回车,广告立无,但是当我看下一页的时候却又发现,又来了一个广告,它奶奶的,玩阴的是吧!

它奶奶的,玩阴的是吧!

那么有没有什么办法可以让我可以一进去网页就可以执行我设计好的脚本呢?这我可想到了,Tampermonkey 这个油猴插件了,注意之前提到过插件在无痕模式下是不可以使用的,但是后面我百度后发现是可以的,但一涉及到 js 我可就不困了呀,还用得着 Adblock ?我直接手写一个!

油猴就是可以实现我们访问网页时帮助我们执行已经设计好的脚本,可是写好了之后,我发现这个去广告的效果并不是特别好?有时候行有时候不行,这是为什么呢?

前面说过,通过分析 HTML 页面结构然后通过 JS 执行相应的 DOM 操作可以帮助我们去删掉广告,那么可以去直接去看访问这个页面时,对展示的 HTML 页面的请求的返回结果进行一个分析

img1.png

罪魁祸首 - ajax

看完之后我就发现了罪魁祸首 - ajax,在请求回来初始 HTML 后,再通过异步请求弹窗广告,然后再渲染到 HTML 上,这也就是为什么插件时灵时不灵,如果访问网页的那一瞬间,网速快了,图片请求回来时,脚本还没运行,这时广告就能够去除,反之则不能,所以我访问这个网站的时候还要靠网速去除广告?

那肯定是不行的,我很快就想到了解决方案

延时运行脚本

网速慢了会导致脚本提前运行,那我延时一下我的脚本不就行了?

setTimeout(() => {
  document.querySelector("#HMRichBox").remove();
}, 1000);

加上时间限制后果然好了很多,但是有时候还是不太行,太短吧,失误率高,太长吧,我已经看完我想看的,或者已经跳过广告部分了,所以这阈值不是能够很好的把控

所以浏览器就是有没有一种可能,就是它可能会有生命周期钩子之类的东西呢?

页面生命周期

  1. DOMContentLoaded —— 浏览器已完全加载 HTML,并构建了 DOM 树,但像 和样式表之类的外部资源可能尚未加载完成。
  2. load —— 浏览器不仅加载完成了 HTML,还加载完成了所有外部资源:图片,样式等。
  3. beforeunload/unload —— 当用户正在离开页面时。

光看文字可能不太清除,看一下控制台 - network 上面的请求分析就可以清除的看到 DOMContentLoaded 和 load 的区别

img2.png

DOMContentLoaded 响应是在 5.62s,而 load 响应是在 5.85s

那么从上面这三个阶段并结合分析结果可以知道,在 DOMContentLoaded 的时候执行我们的脚本是比较合适的,而且更重要的是,在 DOMContentLoaded 响应的时候,广告弹窗的请求已经发送出去了,所以我们的脚本这个时候执行是能够去除广告的,也不再需要去考虑设置时间的多少去执行我们的脚本

总结

这篇文章的敲的代码都是在浏览器中完成的,也就是说,我需要对着网站的紧张刺激的内容一个键一个键的敲代码,而且还经历了三个版本

  1. 控制台
  2. 油猴脚本
  3. 页面生命周期分析

但是实现的内容其实只是为了去除广告,在思考完后,那天晚上其实我已经没有多大兴趣去看网站的实际内容了,违背初心了属于是

那我最后使用了什么去解决广告问题的呢?

其实还是用的 adblock,有些饭还得是让专业的人吃啊

好家伙我他妈直接好家伙

adblock 是采用拦截请求和 CSS 覆盖的方式解决

咱就是说有东西不用,尽 TM 造一些烂轮子

参考资料

load/domContentLoaded 事件、异步/延迟 Js 与 DOM 解析

ADBlock 的实现原理