提问人:gordie 提问时间:5/13/2023 最后编辑:ggorlengordie 更新时间:5/13/2023 访问量:210
如何使用 Cheerio 从字符串中加载和操作 HTML 片段?
How to load and manipulate an HTML fragment from a string with Cheerio?
问:
我正在努力尝试使用 Cheerio 加载 HTML 片段。
var htmlString = '<div class="artist"><i class="user blue circle icon"></i> Skyy</div>';
var $ = cheerio.load(data);
console.info($.html());
输出
<html><head></head><body><div class="artist"><i class="user blue circle icon"></i> Skyy</div></body></html>
我认为,我的问题是 Cheerio 将我的内容包装在 HTML 文档中,这使得直接访问节点变得困难。
我最终可以使用这个选择器,它工作得很好:
var el = $('body').children().first();
但它并不总是有效。例如
var htmlString = '<meta name="description" content="My description">';
var $ = cheerio.load(data);
console.info($.html());
将输出不同类型的文档,其中不起作用:var el = $('body').children().first();
<html><head><meta name="description" content="My description"></head><body></body></html>
那么,有没有办法在不使用选择器的情况下加载 HTML 片段并将其作为 Cheerio 元素访问?
我希望能够在填充的节点上使用 Cheerio 函数,例如 或 。.text()
.html()
.attr()
答:
1赞
code
5/13/2023
#1
cheerio 中有一个选项可以禁止将你的 html 包装在其他标签中,第三个参数(第二个参数包含一个包含其他选项的对象;我们可以将其设置为 null):cheerio.load
const $ = cheerio.load(htmlString, null, false)
console.log($.html()) // <-- just the html, not wrapped
您可以查看源以获取更多信息。
评论
0赞
gordie
5/13/2023
使用最后一个 Cheerio 版本 (^1.0.0-rc.12),它给了我.TS2554: Expected 1-2 arguments, but got 3.
0赞
code
5/13/2023
@gordie我刚刚尝试过,它有效。你确定没有其他干扰吗?
0赞
gordie
5/13/2023
你在用 TypeScript 吗?
0赞
code
5/13/2023
@gordie没有;我想这是 TS 的问题。你用的是哪个版本的?@types/cheerio
0赞
gordie
5/13/2023
类型为 ^0.22.31
0赞
gordie
5/13/2023
#2
我找到了一个解决方案。
通过加载一个空白文档,我可以手动将我的 html 字符串添加到其中 - 所以我确定它会在 中,即使它是 Cheerio 通常会加载到 .<body/>
<head/>
var $ = cheerio.load('');
$('body').append(htmlString);
var el = $('body').children().first();
0赞
ggorlen
5/13/2023
#3
这个答案提供了一个很好的开端,但它没有显示访问标签的一致方式。
$(":root").first();
似乎是提取第一个标签的好方法,未经广泛测试,但在抽查中看起来很有希望。
const cheerio = require("cheerio"); // 1.0.0-rc.12
const {strict: assert} = require("node:assert");
const loadOneTag = html => {
const $ = cheerio.load(html, null, /*isDocument=*/false);
assert.equal($.html(), html);
return $(":root").first();
};
{
// one top-level child
const html = `
<div class="artist"><i class="user blue circle icon"></i> Skyy</div>
`;
assert.equal(loadOneTag(html).attr("class"), "artist");
}
{
// multiple top-level children
const html = `
<div class="artist"><i class="user blue circle icon"></i> Skyy</div>
<p>asdf</p>
`;
assert.equal(loadOneTag(html).attr("class"), "artist");
}
{
// meta tag
const html = `
<meta name="description" content="My description">
`;
assert.equal(loadOneTag(html).attr("name"), "description");
}
评论
0赞
gordie
5/13/2023
似乎有效!除了,根据 TypeScript 的说法,的第二个参数应该是 而不是 。cheerio.load
undefined
null
0赞
ggorlen
5/13/2023
谢谢,如果您愿意,请随时将其插入,但源代码似乎显示 null
,这是我见过的大多数 API 中的标准(“跳过此参数”)。他们应该放入选项参数中。否则,它并不是真正的可读性。这可能是一个向后兼容的问题。但我跑题了......isDocument
0赞
gordie
5/14/2023
Typescript 触发带有 null 的错误,他们希望它未定义(或已定义)。但也许他们的类型不好。
评论