上一主题 下一主题
ScriptCat,新一代的脚本管理器脚本站,与全世界分享你的用户脚本油猴脚本开发指南教程目录
返回列表 发新帖

关于html文本转DOM

[复制链接]

5

主题

70

帖子

116

积分

注册会员

Rank: 2

积分
116

活跃会员热心会员突出贡献三好学生猫咪币纪念章中秋纪念章

发表于 2021-9-11 21:21:46 | 显示全部楼层 | 阅读模式

当我们用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”等等(更多细节请参阅这里)。他相比innerHTML不会去加载图片,在脚本中使用性能优势明显。如果你熟悉XMLHttpRequest,可能知道xhr的responseType可以设置为document,从而直接得到DOM,这本质上也是DOMParser操作,xhr会根据响应头的Content-Type来设置mimeType。注意这2种类型并不完全相同,Content-Type除了包含mimeType,还有charset编码信息等内容(Content-Type的介绍可以看这里)。

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

gm.png

已有2人评分好评 油猫币 贡献 理由
懒男孩 + 1 + 2 + 1 ggnb!
李恒道 + 1 + 1 + 1 ggnb!

查看全部评分 总评分:好评 +2  油猫币 +3  贡献 +2 

123

主题

933

帖子

551

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
551
发表于 2021-9-11 21:25:02 | 显示全部楼层
学到了,大佬严谨
回复

使用道具 举报

6

主题

73

帖子

394

积分

实习版主

Rank: 7Rank: 7Rank: 7

积分
394

活跃会员猫咪币纪念章推广达人宣传达人突出贡献三好学生热心会员中秋纪念章

发表于 2021-9-11 22:18:46 | 显示全部楼层
get 了!!!
是晚柒载哟
回复

使用道具 举报

2

主题

103

帖子

41

积分

新手上路

Rank: 1

积分
41

猫咪币纪念章活跃会员中秋纪念章

发表于 2021-9-11 22:37:42 | 显示全部楼层
np!!!!!学到了
回复

使用道具 举报

72

主题

710

帖子

641

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
641

猫咪币纪念章热心会员活跃会员突出贡献三好学生中秋纪念章

发表于 2021-9-12 09:09:37 | 显示全部楼层
学习了,脚本猫实现的时候注意一下
上不慕古,下不肖俗。为疏为懒,不敢为狂。为拙为愚,不敢为恶。/ 微信公众号:一之哥哥
回复

使用道具 举报

4

主题

85

帖子

30

积分

新手上路

Rank: 1

积分
30

中秋纪念章猫咪币纪念章活跃会员热心会员三好学生

发表于 2021-9-12 13:22:56 | 显示全部楼层
哥哥是 一群小母牛排队上一头小公牛呀,牛逼何其多一个接一个
原来不经意间的小细节竟有大学问!请继续吧
回复

使用道具 举报

0

主题

1

帖子

3

积分

新手上路

Rank: 1

积分
3
发表于 2021-9-16 10:23:11 | 显示全部楼层
可以,学到了,解决了我的疑惑~
回复

使用道具 举报

123

主题

933

帖子

551

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
551
发表于 2021-9-16 11:26:07 | 显示全部楼层
jiabing 发表于 2021-9-16 10:23
可以,学到了,解决了我的疑惑~

哥哥来了!哥哥牛逼!
回复

使用道具 举报

发表回复

本版积分规则

快速回复 返回顶部 返回列表