Javascript jsdom/cheerio大大改变了html

Javascript jsdom/cheerio大大改变了html,javascript,node.js,jsdom,cheerio,Javascript,Node.js,Jsdom,Cheerio,我正在努力清理一个网站,但我对jsdom和cheerio大幅改变它们得到的html都有问题。最值得注意的是,它们删除了一些标记,如table/tr/td标记等 只需使用本地文件(如1.html)并执行以下操作: // with cheerio -> or equivalent with jsdom var $ = require('cheerio').load(fs.readFileSync(path)); fs.writeFileSync('2.html', $.html()); #

我正在努力清理一个网站,但我对jsdom和cheerio大幅改变它们得到的html都有问题。最值得注意的是,它们删除了一些标记,如table/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
<

.....
//与cheerio->或与jsdom等效
var$=require('cheerio').load(fs.readFileSync(path));
fs.writeFileSync('2.html',$.html());
#猛击
$>diff 1.html 2.html
.....
<


编辑:我意识到这也是某种浏览器问题。如果你用wget下载页面并用cheerio粘贴HTML,你会得到一个不同的HTML是的,但是浏览器在解析DOM时删除了标记,这让我相信cheerio/jsdom输出了时髦的HTML


我还通过HTMLW3验证程序运行了该页面,在doctype不允许将元素放置在特定位置方面出现了很多错误,但在无效标记方面没有任何错误。看起来输入的html格式不正确
$.html()
序列化当前DOM表示,除非输入的html语法正确,否则不会生成相同的html

要理解为什么会发生这种情况,请思考在封面下会发生什么。Cheerio将HTML文本解析为规范化的数据结构。这个数据结构就是我们所说的DOM:Document对象模型。HTML只是这个模型的文本表示;cheerio解析HTML后,会丢弃输入文本(因为它不再需要它)

调用
$.html()
时,cheerio必须将DOM数据结构转换回文档的文本表示形式。为此,它在DOM树上递归,并为每个节点生成HTML。原始输入HTML字符串与输出HTML没有任何关系,只是DOM中填充了输入HTML

此时,您应该明白,如果输入HTML格式不正确,解析HTML的库以后不可能输出完全相同的HTML。输入文本的解析和规范化必然是有损的:宽容的解析器必须抛出毫无意义的HTML文本


你甚至可以在Chrome中看到这一点:do。在这里,我们也看到了许多差异,特别是在格式错误的表格周围。(有些差异是由于脚本运行和修改DOM造成的。)这些工件的出现原因与ChereIO、jsdom或任何其他HTML解析库的出现原因相同。

看起来您的输入HTML格式不正确
$.html()
序列化当前DOM表示,除非输入的html语法正确,否则不会生成相同的html

要理解为什么会发生这种情况,请思考在封面下会发生什么。Cheerio将HTML文本解析为规范化的数据结构。这个数据结构就是我们所说的DOM:Document对象模型。HTML只是这个模型的文本表示;cheerio解析HTML后,会丢弃输入文本(因为它不再需要它)

调用
$.html()
时,cheerio必须将DOM数据结构转换回文档的文本表示形式。为此,它在DOM树上递归,并为每个节点生成HTML。原始输入HTML字符串与输出HTML没有任何关系,只是DOM中填充了输入HTML

此时,您应该明白,如果输入HTML格式不正确,解析HTML的库以后不可能输出完全相同的HTML。输入文本的解析和规范化必然是有损的:宽容的解析器必须抛出毫无意义的HTML文本


你甚至可以在Chrome中看到这一点:do。在这里,我们也看到了许多差异,特别是在格式错误的表格周围。(有些差异是由于脚本运行和修改DOM造成的。)这些工件产生的原因与cheerio、jsdom或任何其他HTML解析库产生的原因相同。

我来这里搜索相同的问题,(幸运的是)我还在npm上找到了一个名为tidyHtml的包。这个名字不言自明,下面是它的链接。虽然它目前与2年前的最后一次提交不活动,但它正在做这项工作

清除HTML与运行以下函数一样简单:

var tidy = require('htmltidy2').tidy;
tidy('<table><tr><td>badly formatted html</tr>', function(err, html) {
    console.log(html);
});
var tidy=require('htmltdy2').tidy;
tidy('格式错误的html',函数(错误,html){
log(html);
});
它将标准化HTML并输出以下内容:

<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<table>
<tr>
<td>badly formatted html</td>
</tr>
</table>
</body>
</html>

格式错误的html

我将它与cheerio结合使用,效果非常好。希望它能帮助别人。

我来这里是为了寻找同样的问题,幸运的是,我在npm上也找到了一个名为tidyHtml的包。这个名字不言自明,下面是它的链接。虽然它目前与2年前的最后一次提交不活动,但它正在做这项工作

清除HTML与运行以下函数一样简单:

var tidy = require('htmltidy2').tidy;
tidy('<table><tr><td>badly formatted html</tr>', function(err, html) {
    console.log(html);
});
var tidy=require('htmltdy2').tidy;
tidy('格式错误的html',函数(错误,html){
log(html);
});
它将标准化HTML并输出以下内容:

<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<table>
<tr>
<td>badly formatted html</td>
</tr>
</table>
</body>
</html>

格式错误的html

我将它与cheerio结合使用,效果非常好。希望它能帮助别人。

考虑到html很可能是错误的,你知道我有什么办法可以避免这种情况吗?myeah我明白了,我的问题是,所有浏览器都能正确解析这种格式错误的html。我在问是否有某种方法可以在服务器端做到这一点。我使用wget获取html,因此dom操作不会发生,因此理论上应该有一种方法可以在不改变浏览器操作的情况下对其进行解析:)当然,您可以解析它,但无法对其进行重新序列化(
$.html()
)。如果您需要以任何方式修改DOM并将其保存回HTML,那么您就太倒霉了。你可以试试归档