5月29日 00:50

Cheerio 使用中有哪些常见坑?怎么解决?

最常见的五大坑:①中文乱码——需要用 iconv-lite 按实际编码解码,别依赖 axios 自动处理;②选择器找不到元素——先 $.html() 检查 HTML 是否完整加载,再逐步缩小选择器范围调试;③拿不到动态内容——Cheerio 不执行 JS,要么换 Puppeteer 要么直接调后端 API;④大文件内存溢出——分批处理或流式解析,别一次全 load 进来;⑤XML 解析报错——必须加 { xmlMode: true } 选项,否则自闭合标签和命名空间都会出问题。

追问

中文乱码具体怎么处理? axios 设置 responseType: 'arraybuffer' 拿到原始字节,先从 Content-Type 或 meta 标签检测编码,再用 iconv.decode(buf, charset) 转码。GBK 页面不转码必乱。

选择器没匹配到元素,排查步骤是什么? 第一步 console.log($.html()) 看 HTML 是否完整;第二步从最外层选择器开始逐步缩小;第三步用 :contains() 按文本内容定位;第四步确认元素不在 iframe 或 shadow DOM 中。

处理大文件怎么避免内存泄漏? 分批 .slice(i, i+batchSize) 处理,每批处理完置空引用;更优方案是用 stream 按 </item> 分割,逐块 cheerio.load 解析,内存恒定。

XML 模式和 HTML 模式有什么区别? xmlMode: true 会保留大小写(HTML 模式全部转小写)、保留自闭合标签、不补全缺失的闭合标签。解析 RSS/SVG/配置文件必须开启,否则数据丢失。

提取的文本满是空白字符怎么办? .text() 结果链式调用 .replace(/\s+/g, ' ').trim(),或在 load 时加 { normalizeWhitespace: true },但后者会把换行也合并成空格,按需选择。

写段代码

javascript
// 正确处理 GBK 编码页面 const resp = await axios.get(url, { responseType: 'arraybuffer' }); const charset = resp.headers['content-type']?.match(/charset=([^;]+)/i)?.[1] || 'utf-8'; const html = charset.toLowerCase() === 'utf-8' ? resp.data.toString() : iconv.decode(Buffer.from(resp.data), charset); const $ = cheerio.load(html);
标签:NodeJSCheerio