cheerio 默认以 html 模式解析文档,对自定义命名空间标签(如 `idx:orth`)和深层嵌套的 `div` 结构可能误判为无效或忽略闭合,导致 `.text()` 返回不完整内容;启用 `xml: true` 可强制严格解析,确保所有子元素(包括命名空间标签和嵌套 div)被完整保留。
在使用 Cheerio 处理含命名空间(如 idx:entry、idx:orth)或复杂嵌套结构的 HTML 片段时,你可能会遇到“部分元素丢失”的现象——例如 $('body idx\\:entry').eq(0).text() 仅返回前两个子节点(idx:orth 和第一个 div)的文本,而跳过了第三个 div 中的关键内容(如释义、例句或交叉引用)。这并非 Cheerio 的 bug,而是其默认解析模式与文档实际结构不匹配所致。
Cheerio 提供两种核心解析模式:
(含 idx:/mbp: 命名空间)、SVG 或自定义 XML 文档。在你的 tmp.html 示例中,idx:entry 下的第三个 div 包含多层嵌套(div > div > div > span > i + div > div > a),HTML 模式可能因标签未闭合感知偏差或命名空间忽略,导致该分支未被正确挂载到 DOM 树中;而 tmp2.html 因结构相对线性(无深层 或混合 层级),恰好未触发该限制,故表现正常。
✅ 正确做法是显式启用 XML 模式:
const fs = require('fs');
const cheerio = require('cheerio');
const data = fs.readFileSync('tmp.html', 'utf8');
// 关键:传入 { xml: true } 选项
const $ = cheerio.load(data, {
xml: true, // 启用严格 XML 解析
// 注意:XML 模式下不支持 html5 语法糖(如自闭合
需写为
),但本例无需改动
});
// 现在可完整获取所有子节点文本
const entryText = $('body idx\\:entry').eq(0).text().trim();
console.log(entryText);
// 输出预期结果:
// abaniquear
// abaniquear
// vt
// (Andes)
// see also: abanicar⚠️ 注意事项:
总结:当 Cheerio 表现异常(元素丢失、文本截断、命名空间不可选),优先检查解析选项——xml: true 往往是解决“神秘缺失”的最简、最可靠方案。