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:blankreferrer
仅仅影响document.referrer的值。默认没有引用(即为空字符串)contentType
影响document.contentType的值,是按照HTML解析文档还是 XML来解析。它的值如果不是text/html或XML mime type值的话将会抛出异常。默认值为text/htmluserAgent
影响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 协议 ,转载请注明出处!