bounty将在12小时后过期。回答此问题可获得+150声望奖励。user3840170希望引起更多关注此问题。
我正在编写一个在https://example.net
上运行的用户脚本,它对来自https://example.com
的HTML文档发出fetch
请求,我希望将这些HTML文档解析为HTML DOM树。fetch
API只给我原始的HTML源代码。我可以自己使用DOMParser
解析它,但是我遇到了一个相对链接的问题。假设来自https://example.com
的文档包含如下内容:
<!DOCTYPE html>
<html>
<head>
<body>
<p> <a href="/foo">hello!</a>
如果我获取body > p > a
元素的DOM节点,并读取其href
属性,我获得的值将是https://example.net/foo
。这是因为DOMParser
将环境文档的源位置分配给解析结果。我希望将文档的实际源分配给它,以便正确解析相对链接。
目前我能想到的解决方法只有:
- 将
<base>
元素注入DOM树,这可能会干扰实际HTML源代码中的<base>
标记 - 使用
document.implementation.createHTMLDocument()
,然后使用.write()
,这会给我一个带有空白源位置的文档,其中相对链接至少不会被错误解析(但根本不会被解析)。除了这在用户脚本中不起作用:它抛出一个SecurityError
。 - 使用
Proxy
拦截对href
属性的访问,该属性似乎太重,无法轻松地放入用户脚本中 - 包括一个用户级HTML解析器和DOM实现,这看起来又太麻烦了
我也意识到,从.text()
获得的Unicode文本解析HTML将绕过HTML编码检测算法。我自己可以接受,因为我感兴趣的网站只使用UTF-8正确地表示在标题中,但这也是一个应该注意的缺陷。理想情况下,HTML文档应该直接从Blob
甚至ReadableStream
解析。
有没有更好的方法来实现我想要的?
2条答案
按热度按时间cqoc49vn1#
使用
XMLHttpRequest
而不是fetch
,它具有将HTML解析为Document
的内置功能。在调用
open()
之后、调用send()
之前,必须通过将字符串"document"
分配给XMLHttpRequest
对象的responseType
属性来显式请求文档。在我的测试中,相对URL被转换为基于源文档的绝对URL。
axr492tv2#
如果您可以将基本元素注入到DOM树中,这将是最简单的方法。
但是,如果考虑另一种可能的方法,您可以使用URL对象基于文档的基本URL构造一个新的绝对URL。例如-
通过这种方式,您可以确保正确地设置相对链接,而不必将基本元素插入DOM树或使用用户态HTML解析器和DOM实现。