用 JS 解析 HTML 字符串

IT技术 javascript html dom html-parsing
2021-01-28 00:45:32

我想解析一个包含 HTML 文本的字符串。我想用 JavaScript 来做。

我尝试了Pure JavaScript HTML Parser 库,但它似乎解析了我当前页面的 HTML,而不是从字符串中解析。因为当我尝试下面的代码时,它会更改我的页面标题:

var parser = new HTMLtoDOM("<html><head><title>titleTest</title></head><body><a href='test0'>test01</a><a href='test1'>test02</a><a href='test2'>test03</a></body></html>", document);

我的目标是从我读取的 HTML 外部页面中提取链接,就像字符串一样。

你知道一个API来做到这一点吗?

6个回答

创建一个虚拟 DOM 元素并将字符串添加到其中。然后,您可以像操作任何 DOM 元素一样操作它。

var el = document.createElement( 'html' );
el.innerHTML = "<html><head><title>titleTest</title></head><body><a href='test0'>test01</a><a href='test1'>test02</a><a href='test2'>test03</a></body></html>";

el.getElementsByTagName( 'a' ); // Live NodeList of your anchor elements

编辑:添加一个 jQuery 答案来取悦粉丝!

var el = $( '<div></div>' );
el.html("<html><head><title>titleTest</title></head><body><a href='test0'>test01</a><a href='test1'>test02</a><a href='test2'>test03</a></body></html>");

$('a', el) // All the anchor elements
@stage我有点迟到了,但你应该能够使用document.createElement('html');保存<head><body>标签。
2021-03-17 00:45:32
请注意:使用此解决方案,如果我执行“alert(el.innerHTML)”,我将丢失 <html>、<body> 和 <head> 标签....
2021-03-19 00:45:32
问题:我需要从 <frame> 标签获取链接。但是使用此解决方案,删除了框架标记...
2021-03-29 00:45:32
我很担心被选为最佳答案。parse()下面解决方案更具可重用性和优雅性。
2021-04-08 00:45:32
看起来您正在将 html 元素放入 html 元素中
2021-04-09 00:45:32

这很简单:

var parser = new DOMParser();
var htmlDoc = parser.parseFromString(txt, 'text/html');
// do whatever you want with htmlDoc.getElementsByTagName('a');

根据 MDN,要在 chrome 中执行此操作,您需要像这样解析为 XML:

var parser = new DOMParser();
var htmlDoc = parser.parseFromString(txt, 'text/xml');
// do whatever you want with htmlDoc.getElementsByTagName('a');

它目前不受 webkit 支持,您必须遵循 Florian 的回答,并且在大多数情况下无法在移动浏览器上使用它是未知的。

编辑:现在得到广泛支持

parse()下面解决方案更具可重用性且特定于 HTML。但是,如果您需要 XML 文档,这很好。
2021-03-14 00:45:32
值得注意的是,创建的文档中的所有相关链接都被破坏了,因为文档是通过继承documentURLof创建window,这很可能与字符串的 URL 不同。
2021-03-18 00:45:32
值得注意的是,您应该调用new DOMParser一次,然后在脚本的其余部分重用同一个对象。
2021-03-20 00:45:32
值得注意的是,在 2016 年 DOMParser 现已得到广泛支持。caniuse.com/#feat=xml-serializer
2021-03-24 00:45:32
如何在对话框或其他东西上显示这个解析的网页?我无法找到解决方案
2021-03-28 00:45:32

编辑:下面的解决方案仅适用于 HTML“片段”,因为删除了 html、head 和 body。我猜这个问题的解决方案是 DOMParser 的 parseFromString() 方法:

const parser = new DOMParser();
const document = parser.parseFromString(html, "text/html");

对于 HTML 片段,此处列出的解决方案适用于大多数 HTML,但在某些情况下不起作用。

例如尝试解析<td>Test</td>. 这个不适用于 div.innerHTML 解决方案、DOMParser.prototype.parseFromString 或 range.createContextualFragment 解决方案。td 标签不见了,只剩下文本。

只有 jQuery 可以很好地处理这种情况。

所以未来的解决方案(MS Edge 13+)是使用模板标签:

function parseHTML(html) {
    var t = document.createElement('template');
    t.innerHTML = html;
    return t.content;
}

var documentFragment = parseHTML('<td>Test</td>');

对于较旧的浏览器,我已将 jQuery 的 parseHTML() 方法提取到一个独立的要点中 - https://gist.github.com/Munawwar/6e6362dbdf77c7865a99

如果您想编写也适用于旧浏览器的向前兼容代码,您可以polyfill<template>标签这取决于您可能还需要polyfill 的自定义元素事实上,您可能只想使用webcomponents.js 一次性填充自定义元素、模板、shadow dom、promise 和其他一些东西。
2021-04-08 00:45:32
var doc = new DOMParser().parseFromString(html, "text/html");
var links = doc.querySelectorAll("a");
安全说明:这将在没有任何浏览器上下文的情况下执行,因此不会运行任何脚本。它应该适用于不受信任的输入。
2021-03-10 00:45:32
我从一个项目中复制了这一行,我习惯于在 javascript 应用程序(不在库中)用 $ 前缀变量。这只是为了避免与图书馆发生冲突。这不是很有用,因为几乎每个变量都有范围,但它曾经很有用。它还(也许)有助于轻松识别变量。
2021-03-14 00:45:32
可悲的是,DOMParser两者都不适用text/html于 chrome,这个 MDN 页面提供了解决方法。
2021-03-28 00:45:32
你为什么要加前缀$此外,如链接的副本中所述text/html它的支持不是很好,必须使用 polyfill 来实现。
2021-04-09 00:45:32

在 Chrome 和 Firefox 中解析 HTML 的最快方法是 Range#createContextualFragment:

var range = document.createRange();
range.selectNode(document.body); // required in Safari
var fragment = range.createContextualFragment('<h1>html...</h1>');
var firstNode = fragment.firstChild;

我建议创建一个辅助函数,如果可用,它使用 createContextualFragment,否则回退到innerHTML。

基准:http : //jsperf.com/domparser-vs-createelement-innerhtml/3

安全说明:这将执行输入中的任何脚本,因此不适用于不受信任的输入。
2021-03-19 00:45:32
另外顺便说一句,IE 11 支持 createContextualFragment。
2021-03-25 00:45:32
请注意,与 (simple) 一样innerHTML,这将执行<img>'s onerror
2021-03-27 00:45:32
一个问题是,像 '<td>test</td>' 这样的 html 会忽略 document.body 上下文中的 td(并且只创建 'test' 文本节点)。OTOH,如果它在模板引擎内部使用那么正确的上下文将可用。
2021-03-30 00:45:32
问题是如何用 JS 解析——而不是 Chrome 或 Firefox
2021-04-09 00:45:32