cxxjackie 发表于 2021-9-11 21:21:46

关于html文本转DOM

当我们用ajax获取数据时,有时返回的是一个页面,获取的response是一段html文本,如果我们想获得某些元素的数据要怎么做呢?可能你第一反应是做正则,但这么一大段文本,正则其实非常难写,写出来也很难看,有没有更优雅的办法呢?答案是转换为DOM(页面的document就是一个DOM),然后就可以用querySelector等方法来操作。如何将string转换为DOM?你可能想到利用innerHTML,先创建一个html元素,然后令其innerHTML = string即可。jquery中也可以直接`$(string)`来实现转换,其本质上也是通过innerHTML实现的,不过由于jquery创建的元素类型为div,会导致转换后的head和body不见了,两部分元素挤到了一起。

innerHTML的思路看似美好,实际存在严重的性能问题:不管你有没有将元素添加到页面中,innerHTML都会预加载其中的图片,这在多数情况下是好事(大部分图片最终都会被添加到页面中),但在我们的脚本里却是坏事。为了测试这一现象,你可以在随便打开一个页面,在控制台输入这行代码:

`document.createElement('html').innerHTML = '<img src="https://bbs.tampermonkey.net.cn/favicon.ico">'`

然后切换到Network标签观察一下,可以看到一张favicon.ico的图片被加载进来了。想象一下有这样一个脚本,从多个链接中读取html,每个都取一点数据,实现一个爬虫类的效果。这种需求并不少见,但如果用innerHTML实现,想想我们会加载多少毫无意义的图片,性能方面简直就是一场灾难。

有没有更好的转换方法?不需要借助第三方库,原生js就可以实现:new DOMParser().parseFromString(),接收2个参数,第1个是你要转换的字符串,第2个是mime类型,形如“text/html”、“text/xml”等等(更多细节请参阅[这里](https://developer.mozilla.org/zh-CN/docs/Web/API/DOMParser))。他相比innerHTML不会去加载图片,在脚本中使用性能优势明显。如果你熟悉XMLHttpRequest,可能知道xhr的responseType可以设置为document,从而直接得到DOM,这本质上也是DOMParser操作,xhr会根据响应头的Content-Type来设置mimeType。注意这2种类型并不完全相同,Content-Type除了包含mimeType,还有charset编码信息等内容(Content-Type的介绍可以看[这里](https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Content-Type))。

在GM_xmlhttpRequest中,也可以设定responseType为document,但是据我测试,至少在部分版本的Tampermonkey中,GM_xmlhttpRequest是直接令mimeType等于响应头的Content-Type,前面提到两种type不一样,当Content-Type中含有charset等字段时,转换就会失败,控制台报TypeError错误(关于这个bug的讨论可以看[这里](https://github.com/Tampermonkey/tampermonkey/issues/1000)和[这里](https://github.com/Tampermonkey/tampermonkey/issues/1239))。其实XMLHttpRequest提供了一个overrideMimeType方法,用于覆盖响应头的Content-Type,GM_xmlhttpRequest也提供了,但实际上该属性没有正确生效。Tampermonkey在后续版本中似乎已经修复了这个bug,但考虑到你的用户不一定会保持更新,**如果你是个脚本开发者,出于兼容性考虑,我不建议使用GM_xmlhttpRequest的document方式**,应该改用text获取文本,再自己做DOMParser转换。

!(data/attachment/forum/202109/11/211245hal0jaqx00dzd6rl.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "gm.png")

李恒道 发表于 2021-9-11 21:25:02

学到了,大佬严谨

无了 发表于 2021-9-11 22:18:46

get 了!!!

syy 发表于 2021-9-11 22:37:42

np!!!!!学到了{:4_97:}

王一之 发表于 2021-9-12 09:09:37

学习了,脚本猫实现的时候注意一下

脚本体验师001 发表于 2021-9-12 13:22:56

哥哥是 一群小母牛排队上一头小公牛呀,牛逼何其多一个接一个
原来不经意间的小细节竟有大学问!请继续吧

jiabing 发表于 2021-9-16 10:23:11

可以,学到了,解决了我的疑惑~

李恒道 发表于 2021-9-16 11:26:07

jiabing 发表于 2021-9-16 10:23
可以,学到了,解决了我的疑惑~

哥哥来了!哥哥牛逼!

wwwwwllllk 发表于 2022-6-19 13:52:13

大佬太牛逼了

灬123 发表于 2022-6-21 11:29:35

牛!学习到了
页: [1] 2
查看完整版本: 关于html文本转DOM