
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 提供两种核心解析模式:
- HTML 模式(默认):宽容、自动修复错误标签、忽略未知命名空间、扁平化或省略“不标准”嵌套(如 div 内再嵌 div 在某些旧规范中被视为可疑),适用于常规网页抓取;
- XML 模式(xml: true):严格、保留所有标签名(含冒号命名空间)、维持原始嵌套层级、不自动修正或丢弃节点,适用于 EPUB、Kindle 格式(含 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⚠️ 注意事项:
- xml: true 会禁用 HTML 特有特性(如 script/style 标签内容自动解码、
的 src 属性自动补全等),但对纯结构提取场景无影响;
- 若文档混有 HTML5 特性(如
ain>、 )且需兼容性,可改用 { xml: false, recognizeSelfClosing: true, decodeEntities: false } 组合调试,但命名空间支持仍受限; - 对于 Kindle/EPUB 索引文件(.html 含 idx: 标签),始终推荐 xml: true ——这是官方文档明确建议的用法;
- 若需同时处理 HTML 和 XML 内容,建议按数据源类型分别配置 cheerio.load() 实例。
总结:当 Cheerio 表现异常(元素丢失、文本截断、命名空间不可选),优先检查解析选项——xml: true 往往是解决“神秘缺失”的最简、最可靠方案。










