parse5 vs jsdom vs cheerio vs domino
Node.js 环境下的 HTML 解析与 DOM 模拟方案
parse5jsdomcheeriodomino类似的npm包:

Node.js 环境下的 HTML 解析与 DOM 模拟方案

cheerio、domino、jsdom 和 parse5 都是用于在 Node.js 中处理 HTML 内容的工具,但它们的定位完全不同。cheerio 提供了类似 jQuery 的 API,专注于快速抓取和遍历;jsdom 实现了完整的 Web 标准 DOM,适合需要浏览器环境的测试;domino 是一个轻量级的 DOM 实现,适合对性能敏感的场景;parse5 则是底层的 HTML 解析器,返回抽象语法树,适合构建自定义工具。

npm下载趋势

3 年

GitHub Stars 排名

统计详情

npm包名称
下载量
Stars
大小
Issues
发布时间
License
parse5169,173,6933,936337 kB396 个月前MIT
jsdom113,408,97821,7045.53 MB2987 天前MIT
cheerio27,017,82130,5131.01 MB599 个月前MIT
domino1,814,740791818 kB302 个月前BSD-2-Clause

Node.js HTML 处理库深度对比:Cheerio vs Domino vs JSDOM vs Parse5

在 Node.js 中处理 HTML 是一门技术活。cheerio、domino、jsdom 和 parse5 都能解析 HTML,但它们的内部机制和适用场景差别很大。选错工具可能导致代码运行缓慢,或者无法通过测试。本文将从核心机制、API 风格、环境模拟和实际场景四个方面进行深度对比。

🛠️ 核心机制:解析器 vs 完整 DOM

这四个库的根本区别在于它们是否实现了完整的文档对象模型(DOM)。

cheerio 只解析 HTML 并提供遍历 API,不模拟浏览器环境。

  • 它加载 HTML 字符串,构建一个轻量级的内存结构。
  • 没有 window 对象,没有样式计算,没有布局。
// cheerio: 仅加载结构
const cheerio = require('cheerio');
const $ = cheerio.load('<html><body><h1>Hello</h1></body></html>');
// 无法访问 window 对象
// console.log(window); // undefined

jsdom 实现了完整的 Web 标准 DOM,包括 window 和 document。

  • 它模拟了一个headless 浏览器环境。
  • 支持事件、样式(部分)和 DOM 操作。
// jsdom: 完整环境
const { JSDOM } = require('jsdom');
const dom = new JSDOM('<html><body><h1>Hello</h1></body></html>');
// 可以访问 window 对象
console.log(dom.window.document.querySelector('h1').textContent);

domino 实现了 DOM 标准,但比 jsdom 更轻量。

  • 它提供了 document 对象,但通常不包含完整的 window 对象。
  • 适合只需要 DOM 接口但不需要浏览器全局对象的场景。
// domino: 轻量 DOM
const domino = require('domino');
const doc = domino.createDocument('<html><body><h1>Hello</h1></body></html>');
// 有 document,但通常没有 window
console.log(doc.querySelector('h1').textContent);

parse5 只是一个解析器,返回抽象语法树(AST)。

  • 它不提供 querySelector 或 DOM 遍历方法。
  • 你需要自己编写代码来遍历树结构。
// parse5: 纯解析器
const parse5 = require('parse5');
const ast = parse5.parse('<html><body><h1>Hello</h1></body></html>');
// 返回的是 AST 对象,不是 DOM
console.log(ast.childNodes[0].tagName); // 'html'

📝 API 风格:jQuery vs 标准 DOM vs 原始树

API 的设计直接影响开发效率。

cheerio 使用类似 jQuery 的链式调用。

  • 熟悉前端开发的工程师可以立即上手。
  • 选择器语法与浏览器一致。
// cheerio: jQuery 风格
const $ = cheerio.load('<ul><li class="item">A</li></ul>');
const text = $('.item').text(); 
// 链式调用

jsdom 使用标准的浏览器 DOM API。

  • 代码可以直接从浏览器移植到 Node.js。
  • 支持 querySelector、addEventListener 等。
// jsdom: 标准 DOM 风格
const dom = new JSDOM('<ul><li class="item">A</li></ul>');
const text = dom.window.document.querySelector('.item').textContent;
// 标准 API

domino 也使用标准的 DOM API。

  • 与 jsdom 的用法非常相似。
  • 主要区别在于缺少部分浏览器特有属性。
// domino: 标准 DOM 风格
const doc = domino.createDocument('<ul><li class="item">A</li></ul>');
const text = doc.querySelector('.item').textContent;
// 标准 API

parse5 需要手动遍历 AST。

  • 没有内置的选择器引擎。
  • 适合需要自定义遍历逻辑的高级用户。
// parse5: 手动遍历
const ast = parse5.parse('<ul><li class="item">A</li></ul>');
// 需要递归查找节点
function findLi(node) {
  if (node.tagName === 'li') return node;
  if (node.childNodes) {
    for (let child of node.childNodes) {
      const res = findLi(child);
      if (res) return res;
    }
  }
}
const li = findLi(ast);

🌐 环境模拟:窗口对象与事件

是否需要模拟浏览器全局环境是选择的关键。

cheerio 完全没有环境模拟。

  • 不能运行依赖 window 或 document 的客户端脚本。
  • 适合纯数据提取。
// cheerio: 无环境
const $ = cheerio.load('<div></div>');
// 无法执行脚本或触发事件

jsdom 提供完整的 window 对象。

  • 可以运行简单的客户端脚本(需配置)。
  • 支持触发 DOM 事件。
// jsdom: 完整环境
const dom = new JSDOM('<div></div>', { runScripts: 'dangerously' });
dom.window.document.dispatchEvent(new dom.window.Event('click'));

domino 提供 document 但 window 支持有限。

  • 适合操作 DOM 结构,但不适合模拟交互。
  • 性能比 jsdom 好。
// domino: 有限环境
const doc = domino.createDocument('<div></div>');
// 通常不推荐用于事件模拟

parse5 不涉及环境模拟。

  • 它只关心 HTML 文本到树结构的转换。
  • 与运行时环境无关。
// parse5: 无环境
const ast = parse5.parse('<div></div>');
// 纯粹的数据结构

🚀 实际场景推荐

场景 1:网页爬虫与数据提取

你需要从成千上万个页面中提取标题和价格。

  • ✅ 最佳选择:cheerio
  • 为什么?速度快,API 简单,内存占用低。
// cheerio 示例
const $ = cheerio.load(html);
const price = $('.price').text();

场景 2:前端单元测试

你需要测试一个依赖 document.querySelector 的组件。

  • ✅ 最佳选择:jsdom
  • 为什么?它提供了最接近浏览器的环境,测试库(如 Jest)默认使用它。
// jsdom 示例
const dom = new JSDOM(html);
global.document = dom.window.document;

场景 3:高性能 HTML 清洗

你需要清理用户提交的 HTML,去除危险标签,且并发量很大。

  • ✅ 最佳选择:parse5
  • 为什么?它是纯解析器,开销最小,适合构建自定义清洗逻辑。
// parse5 示例
const ast = parse5.parse(html);
// 自定义遍历去除脚本标签

场景 4:轻量级 DOM 操作

你需要操作 DOM 结构,但 jsdom 启动太慢。

  • ✅ 最佳选择:domino
  • 为什么?它比 jsdom 快,且提供了标准的 DOM API。
// domino 示例
const doc = domino.createDocument(html);
doc.body.innerHTML = '';

📊 总结对比表

特性cheeriojsdomdominoparse5
核心类型jQuery 兼容层完整 DOM 模拟轻量 DOM 实现HTML 解析器
API 风格$().find()document.querySelectordocument.querySelectorAST 遍历
Window 对象❌ 无✅ 完整⚠️ 有限/无❌ 无
执行脚本❌ 不支持✅ 支持 (需配置)❌ 不支持❌ 不支持
性能⚡ 极快🐢 较慢⚡ 快⚡ 极快
主要用途爬虫、数据提取测试、SSR轻量 DOM 操作编译器、工具链

💡 最终建议

cheerio 是爬虫和数据提取的首选工具 — 它简单、快速且足够强大。如果你的任务只是读取 HTML 内容,不要引入更重的库。

jsdom 是测试和模拟浏览器环境的黄金标准 — 当你的代码依赖 window 或 DOM 事件时,它是唯一可靠的选择。尽管它比较重,但兼容性无可替代。

domino 是一个不错的中间选项 — 当你需要 DOM API 但 jsdom 太慢时使用。但要注意它的维护状态不如 jsdom 活跃。

parse5 是底层构建者的工具 — 如果你正在编写一个 HTML 编译器或需要流式处理,它是基础。对于普通业务逻辑,它过于原始。

核心原则:不要为了杀鸡用牛刀。如果只是提取文本,cheerio 就够了;如果需要运行测试,jsdom 是必须的。

如何选择: parse5 vs jsdom vs cheerio vs domino

  • parse5:

    选择 parse5 如果你需要构建自己的 HTML 处理工具,或者需要流式解析大文件。它不提供 DOM 操作 API,只负责解析和序列化,适合底层开发。如果你需要完全控制解析过程,选它。

  • jsdom:

    选择 jsdom 如果你需要在 Node.js 中运行依赖浏览器 DOM API 的代码,比如前端单元测试或服务端渲染预演。它是标准兼容性最好的选择,支持窗口对象和事件模拟。

  • cheerio:

    选择 cheerio 如果你需要做网页爬虫或数据提取,且不需要真正的浏览器环境。它的类 jQuery API 学习成本低,处理速度快,适合大多数静态 HTML 分析任务。如果你只需要提取文本或属性,它是最高效的选择。

  • domino:

    选择 domino 如果你需要一个轻量的 DOM 环境,但 jsdom 太重了。注意它的维护频率较低,适合内部工具或对标准兼容性要求不高的场景。它在内存占用上比 jsdom 更有优势。

parse5的README

parse5

parse5

HTML parser and serializer.

npm install --save parse5

📖 Documentation 📖


List of parse5 toolset packages

GitHub

Online playground

Changelog