JSDOM/Cheerio 大大改变了 HTML
jsdom/cheerio considerably alter html
我正在尝试抓取一个网站,但我遇到了jsdom和cheerio的问题,极大地改变了他们得到的html。最值得注意的是,它们删除了一些标签,例如表/tr/td 标签等
只需让一个本地文件说 1.html 并执行以下操作:
// with cheerio -> or equivalent with jsdom
var $ = require('cheerio').load(fs.readFileSync(path));
fs.writeFileSync('2.html', $.html());
# bash
$> diff 1.html 2.html
.....
< <tr><td colspan="5"><a id="stats" name="stats"></a><div class="titlebar1" style="margin-top: 12px;margin-bottom: 4px;"><h2>Stats</h2><div class="element"><img src="img/element/10.png" /></div><div class="elementborder"><img src="img/elementborder.png" /></div></div></td></tr></table></td></div>
---
> <tr><td colspan="5"><a id="stats" name="stats"></a><div class="titlebar1" style="margin-top: 12px;margin-bottom: 4px;"><h2>Stats</h2><div class="element"><img src="img/element/10.png"></div><div class="elementborder"><img src="img/elementborder.png"></div></div></div></td></tr>
54,57c53,56
<
.....
编辑:我意识到这很可能是由于无效的HTML,我的问题是无论如何我都可以避免这种情况,就好像您在浏览器中正常查看页面一样,元素就在那里
更准确地说,我试图刮擦这个:http://www.puzzledragonx.com/en/monster.asp?n=1
编辑:我意识到这也是某种浏览器问题。如果您使用 wget 下载页面并使用 cheerio 粘贴 HTML,您将拥有不同的 html 是的,但是浏览器在解析 DOM 时会删除标签,这让我相信 cheerio/jsdom 输出时髦的 html
我还通过html w3验证器运行该页面,并且有很多关于doctype不允许将元素放置在某个位置的错误,但没有关于无效标记的错误
看起来您的输入 HTML 格式不正确。 $.html()
序列化当前的 DOM 表示形式,除非输入 HTML 语法正确,否则不会产生相同的 HTML。
要了解为什么会发生这种情况,请考虑一下幕后发生了什么。 Cheerio 将 HTML 文本解析为规范化的数据结构。 这种数据结构就是我们所说的 DOM:文档对象模型。 HTML 只是此模型的文本表示形式;在Cheerio解析HTML之后,它会丢弃输入文本(因为它不再需要它)。
当你调用$.html()
时,cheerio必须将DOM数据结构转换回文档的文本表示形式。 为此,它会递归 DOM 树并为每个节点生成 HTML。 原始输入 HTML 字符串与输出 HTML 无关,除了 DOM 填充了输入 HTML 的事实。
此时,您应该明白为什么如果输入 HTML 格式不正确,解析 HTML 的库以后无法输出完全相同的 HTML。 输入文本的解析和规范化必然是有损的:一个宽容的解析器必须抛弃没有意义的 HTML 文本。
即使在 Chrome 中,您也可以看到这一点:对页面的源代码和 document.documentElement.outerHTML
返回的字符串进行差异。 在这里,我们也看到了许多差异,尤其是在格式错误的表格周围。 (有些差异是脚本运行和更改 DOM 的结果。 这些工件的发生原因与 cheerio、jsdom 或任何其他 HTML 解析库的原因相同。
我来到这里寻找同样的问题,(幸运的是)我还在 npm 上找到了一个名为 tidyHTML 的包。该名称是不言自明的,这是 https://www.npmjs.com/package/htmltidy2 的链接。虽然它目前在 2 年前最后一次提交时处于非活动状态,但它正在完成这项工作。
清理 HTML 就像运行以下函数一样简单:
var tidy = require('htmltidy2').tidy;
tidy('<table><tr><td>badly formatted html</tr>', function(err, html) {
console.log(html);
});
它将标准化 HTML 并将输出以下内容:
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<table>
<tr>
<td>badly formatted html</td>
</tr>
</table>
</body>
</html>
我将其与cheerio结合使用,结果非常好。希望它能帮助某人。
- 这是关于Jquery/JS的,如果我改变元素's HTML-我可以对它执行其他Jquery/JS操作吗
- HTML 按钮到大/CSS 不改变大小
- 正在用jQuery改变HTML结构
- Javascript:改变内部HTML与显示
- JSDOM/Cheerio 大大改变了 HTML
- 在javascript中显示表格而不改变html
- 在 HTML 文件中放置脚本标记是否会改变输出
- HTML中的JavaScript正在改变背景
- html按钮不会改变颜色
- HTML/JS:如何使用JS改变select type的选项值
- 如何在HTML画布中改变线条粗细?
- 在框架html中改变下拉值
- 用JavaScript改变HTML中的Tex字符串
- 基于查看区域,使用javascript动态改变html对象中嵌入flash文件的大小
- 如何改变对象's html
- 在Razor html中使用button和JS改变一个值
- 当分辨率改变时,具有固定单元格的HTML表
- 改变CSS的HTML在计算机计时
- 改变一个HTML元素在UIWebVIew中的位置
- 当HTML改变时更新选择器的jQuery设计模式