
cheerio 默认以 html 模式解析文档,会自动修正不规范标签(如自定义命名空间标签 `idx:entry`),导致嵌套 `div` 被错误剥离;启用 `xml: true` 可保留原始结构并正确提取全部子元素文本。
在使用 Cheerio 处理含 XML 命名空间(如 idx:entry、mbp:frameset)或非标准 html 结构的文档时,你可能会遇到看似“丢失”元素的问题——尤其是深层嵌套的
内容未被 text() 方法捕获。这并非 Cheerio 的 bug,而是其默认解析模式与文档实际结构不匹配所致。
默认情况下,cheerio.load(htmlString) 以 HTML 模式 运行:它会模拟浏览器 dom 行为,自动修复/忽略非法标签、折叠空白、规范化命名空间前缀(如将 idx:orth 视为未知标签并降级处理),甚至可能提前截断或跳过无法识别的父子关系。在你的 tmp.html 中,
因其复杂嵌套(含 span、i、a 等)及命名空间上下文,在 HTML 模式下被解析器误判为“不可见”或“无效结构”,从而未纳入 .text() 的遍历范围。
✅ 正确解法是显式启用 XML 模式:
const fs = require('fs'); const cheerio = require('cheerio'); const data = fs.readFileSync('tmp.html', 'utf8'); // 关键:传入 { xml: true } 选项 const $ = cheerio.load(data, { xml: true }); // 现在可完整获取所有子节点文本 const entryText = $('body idx\:entry').eq(0).text().trim(); console.log(entryText); // 输出:abaniquear vt (Andes) see also: abanicar ✅
⚠️ 注意事项:
立即学习“前端免费学习笔记(深入)”;
- xml: true 会禁用 HTML 自动修复(如闭合缺失标签、转换大小写),因此文档必须格式良好(良好嵌套、正确闭合、合法实体);
- 命名空间前缀(如 idx:)需在选择器中转义:idx\:entry(双反斜杠因 js 字符串+css 选择器双重转义);
- 若混合使用 HTML 语义标签(如 、)和 XML 标签,确保它们在 XML 模式下仍被正确识别(通常无问题,但避免依赖 innerHTML 类似行为);
- 不要混用 xml: true 与 script: false 或 decodeEntities: false 等可能破坏文本解析的选项。
? 总结:当 Cheerio 表现异常(元素“消失”、文本截断、属性丢失),优先检查解析模式——对含自定义命名空间、EPUB/MOBI 索引标记(idx:*)、svg 或 xhtml 片段的文档,{ xml: true } 是可靠且必要的配置。