Javascript-浏览器环境模拟
本文最后更新于:2021年7月3日 下午
jsdom
jsdom 是一个纯粹由 javascript 实现的一系列 web标准,特别是 WHATWG 组织制定的DOM和 HTML 标准,用于在 nodejs 中使用
大体上来说,该项目的目标是模拟足够的 Web浏览器子集,以便用于测试和挖掘真实世界的Web应用程序
链接
github地址:https://github.com/jsdom/jsdom
安装
1 |
|
基本用法
1 |
|
为了使用 jsdom,主要用到jsdom主模块的一个命名导出的 jsdom 构造函数
往构造器传递一个字符串,将会得到一个 jsdom 构造实例对象,这个对象有很多实用的属性,特别是 window 对象:
1 |
|
(注意: jsdom会像浏览器一样解析传递的 HTML,包括隐含的<html>
, <head>
和 <body>
标记)
生成的对象是 JSDOM类 的一个实例,其中包括 window 对象在内的许多有用的属性和方法
一般来说,它可以用来从“外部”对jsdom进行操作,而这些操作对于普通DOM API来说是不可能的
对于不需要任何功能的简单场景,推荐使用类似的编码模式
1 |
|
简单选项
1 |
|
url
设置的值可以通过window.location
,document.URL
和document.documentURI
来返回,并会影响文档中相关URL的解析以及获取子资源时使用的同源限制和referrer。默认值为about:blank
referrer
仅仅影响document.referrer
的值。默认没有引用(即为空字符串)contentType
影响document.contentType
的值,是按照HTML解析文档还是 XML来解析。它的值如果不是text/html
或XML mime type
值的话将会抛出异常。默认值为text/html
userAgent
影响navigator.userAgent
的值以及请求子资源时发送的User-Agent
头。默认值为Mozilla / 5.0($ {process.platform})AppleWebKit / 537.36(KHTML,如Gecko)jsdom / $ {jsdomVersion}
includeNodeLocations
保留由HTML解析器生成的位置信息,允许您使用nodeLocation()
方法(如下所述)检索它
它还能确保在<script>
元素内运行的代码的异常堆栈跟踪中报告的行号是正确的
默认值为false
以提供最佳性能,并且不能与XML内容类型一起使用,因为我们的XML解析器不支持位置信息
请注意,url 和referrer在使用之前已经被规范化了,例如
如果你传入https:example.com
,jsdom会自动规范化解释为https://example.com/
如果你传递了一个不可解析的URL,该调用将抛出错误。
(URL根据URL标准进行分析和序列化)
执行脚本
jsdom 最强大的功能是它可以在 jsdom 中执行脚本。这些脚本可以修改页面的内容并访问 jsdom 实现的所有Web平台API
但是,这在处理不可信内容时也非常危险
jsdom沙箱并不是万无一失的,在DOM的<script>
内部运行的代码如果足够深入,就可以访问 Node.js
环境,从而访问您的计算机
因此,默认情况下,执行嵌入在HTML中的脚本的功能是禁用的:
1 |
|
要在页面内启用脚本,可以使用 runScripts:"dangerously"
选项:
1 |
|
只有在提供给 jsdom 的代码是你已知道是安全的代码时方可使用它。如果您运行了任意用户提供的或 Internet 上的不可信的 Node.js 代码,可能会危及您的计算机
假如你想通过<script src="">
来执行外部脚本,你需要确保已经加载了它们。为此,请添加选项 resources:"usable"
如下所述
请注意,除非runScripts
设置为dangerously
,否则事件处理程序属性(如<div onclick =“”>
)也将不起作用。(但是,事件处理函数属性,比如div.onclick = ...
,将无视runScripts
参数 并且会起作用)
如果您只是试图从“外部”执行脚本,而不是通过<script>
元素(和内联事件处理程序)从内部运行“,则可以使用runScripts: "outside-only"
选项,该选项会启用window.eval
1 |
|
由于性能原因,默认情况下会关闭此功能,但可以安全启用
请注意,我们强烈建议不要试图通过将 jsdom 和 Node 全局环境混合在一起(例如,通过执行global.window = dom.window
)来“执行脚本”,然后在 Node 全局环境中执行脚本或测试代码
相反,您应该像对待浏览器一样对待 jsdom,并使用 window.eval
或runScripts: "dangerously"
来运行需要访问 jsdom 环境内的 DOM 的所有脚本和测试
例如,这可能需要创建一个browserify包作为<script>
元素执行 - 就像在浏览器中一样
Cookie jars(存储Cookie的容器)
像网页浏览器一样,jsdom 也具有cookie jar的概念,存储 HTTP cookie 在文档的同一个域上一个 URL,并且没有标记为 HTTP only 的 cookies,可以通过 document.cookie API 来访问。此外,Cookie jar 中的所有 cookie 都会影响子资源的 http 加载
默认情况下,JSDOM构造函数将返回一个带有空cookie的实例。要创建自己的cookie jar并将其传递给jsdom,可以通过以下代码来覆盖默认值
1 |
|
如果您想要在多个 jsdoms 中共享同一个 cookie jar,或者提前使用特定的值来填充 cookie jar,这将非常有用
Cookie jar 包由 tough-cookie 包提供的。jsdom.CookieJar 构造函数是 tough-cookie cookie jar 的子类,并且默认设置了looseMode:true选项,因为它更符合浏览器的行为方式
如果您想自己使用 tough-cookie 的方法和类,则可以使用 jsdom.toughCookie 模块导出来访问使用 jsdom 打包的 tough-cookie 模块实例
API
见github文档: https://github.com/jsdom/jsdom#jsdom-object-api
abab
jsdom 提供的 window对象 并没有 atob
与btoa
这两个处理 base64 字符的方法。使用这个库可以获取到一样的方法,既标准 base64 编码解码方法
链接
github地址:https://github.com/jsdom/abab
安装
1 |
|
btoa (base64 encode)
1 |
|
atob (base64 decode)
1 |
|
有效字符
根据规范,btoa 将接受字符串“仅包含 U + 0000
到 U + 00FF
范围内的字符”
如果传递的字符串的字符大于 U + 00FF
,则 btoa
将返回 null
如果传递的atob
字符串不是base64
合法的,则它还将返回null
在这两种情况下,当返回null
时,规范都要求抛出InvalidCharacterError
类型的DOMException
在浏览器中使用
如果希望在浏览器使用
1 |
|
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!