cheerio vs domino vs jsdom vs parse5
Node.js におけるサーバーサイド HTML パーシングと DOM 操作ライブラリの比較
cheeriodominojsdomparse5類似パッケージ:

Node.js におけるサーバーサイド HTML パーシングと DOM 操作ライブラリの比較

cheeriodominojsdomparse5 は、Node.js 環境で HTML を処理するための代表的なライブラリです。これらはサーバーサイドでのスクレイピング、テスト、HTML 変換などの用途に使われますが、内部の実装アプローチと提供される機能には大きな違いがあります。jsdom はブラウザの DOM 仕様をほぼ完全に実装しており、ブラウザ依存のコードをテストする際に最適です。cheerio は jQuery に似た API を提供し、HTML の抽出や操作を軽量かつ高速に行えます。domino は DOM 実装に特化しており、ウィンドウオブジェクトを持たない軽量な環境を提供します。parse5 は HTML パーサーそのものであり、他のライブラリの基盤としても使われる低レベルなツールです。

npmのダウンロードトレンド

3 年

GitHub Starsランキング

統計詳細

パッケージ
ダウンロード数
Stars
サイズ
Issues
公開日時
ライセンス
cheerio030,3661.01 MB435ヶ月前MIT
domino0788827 kB303ヶ月前BSD-2-Clause
jsdom021,5787.03 MB4161ヶ月前MIT
parse503,899337 kB362ヶ月前MIT

Node.js における HTML 処理ライブラリ:cheerio、domino、jsdom、parse5 の比較

Node.js で HTML を扱う場合、ブラウザと同じように DOM を操作できるか、それとも軽量なパーシングだけで十分かによって選ぶべきツールが変わります。cheeriodominojsdomparse5 はそれぞれ異なる設計思想を持っており、用途によって明確な使い分けが必要です。ここでは、実開発で直面する具体的なシナリオに基づいて、これら 4 つのライブラリを技術的に比較します。

🏗️ 基本アーキテクチャ:DOM 実装 vs パーサー

jsdom は、W3C の DOM 仕様を可能な限り忠実に実装しようとする「フル機能」のライブラリです。

  • ブラウザの windowdocument オブジェクトをエミュレートします。
  • JavaScript の実行機能も含まれており、ページ内のスクリプトを動かすことも可能です。
// jsdom: 完全な DOM 環境
const { JSDOM } = require("jsdom");
const dom = new JSDOM(`<!DOCTYPE html><p>Hello</p>`);
console.log(dom.window.document.querySelector("p").textContent); // "Hello"

cheerio は、DOM 仕様の実装ではなく、サーバーサイドでの HTML 操作に特化したライブラリです。

  • jQuery と非常に似た API を提供します。
  • 内部で parse5 をパーサーとして使用していますが、完全な DOM ツリーは構築しません。
// cheerio: jQuery ライクな API
const cheerio = require("cheerio");
const $ = cheerio.load(`<p>Hello</p>`);
console.log($("p").text()); // "Hello"

domino は、DOM レベル 4 仕様に基づいた軽量な DOM 実装です。

  • window オブジェクトを持たず、document のみを提供します。
  • ブラウザの描画やレイアウト機能は含まれません。
// domino: 軽量な DOM 実装
const domino = require("domino");
const doc = domino.createDocument(`<p>Hello</p>`);
console.log(doc.querySelector("p").textContent); // "Hello"

parse5 は、HTML パーサーおよびシリアライザーそのものです。

  • DOM 操作 API は提供しません。
  • AST(抽象構文木)を生成し、それを元に自分で処理を書くか、他のライブラリに渡します。
// parse5: 純粋なパーサー
const parse5 = require("parse5");
const ast = parse5.parse(`<p>Hello</p>`);
console.log(ast.childNodes[0].tagName); // "p"

⚡ パフォーマンスとリソース消費

処理速度とメモリ使用量は、大規模な HTML を扱う際に重要な要素です。

cheerio は、不要なブラウザ機能を捨てることで最も高速に動作する傾向があります。

  • 単純な要素の抽出や属性の変更であれば、他の追随を許しません。
// cheerio: 高速な操作
const $ = cheerio.load(largeHtmlString);
const titles = $("h1").map((i, el) => $(el).text()).get();

jsdom は機能性が最も高い分、初期化コストとメモリ使用量が大きいです。

  • 複雑な DOM 操作やイベントシミュレーションが必要な場合に真価を発揮します。
// jsdom: 高機能だが重め
const { JSDOM } = require("jsdom");
const dom = new JSDOM(largeHtmlString);
const titles = Array.from(dom.window.document.querySelectorAll("h1")).map(el => el.textContent);

dominojsdom よりも軽量ですが、cheerio ほど最適化されていません。

  • DOM 仕様への準拠が必要な場合の中間選択肢となります。
// domino: 中程度の重さ
const doc = domino.createDocument(largeHtmlString);
const titles = Array.from(doc.querySelectorAll("h1")).map(el => el.textContent);

parse5 はパーシングのみを行うため、単体では比較対象が異なりますが、基盤として非常に高速です。

  • 自分でトラバーサルロジックを書く手間がかかります。
// parse5: 最速のパーシングだが手動作業が必要
const ast = parse5.parse(largeHtmlString);
// ここから自分で AST を走査して h1 タグを探す必要がある

🧪 テスト環境での利用適性

フロントエンドのテスト自動化において、どのライブラリを選ぶかはテストの目的によります。

jsdom は、ブラウザの挙動を再現する必要があるテストに最適です。

  • jestvitest などのテストランナーでデフォルト環境としてよく使われます。
  • click()dispatchEvent() などのイベント操作も可能です。
// jsdom: イベント処理のテスト
const { JSDOM } = require("jsdom");
const dom = new JSDOM(`<button id="btn">Click</button>`);
const btn = dom.window.document.getElementById("btn");
btn.click(); // イベントが発火する

cheerio は、HTML の出力内容を確認するスナップショットテストや、スクレイピングロジックのテストに向いています。

  • イベント処理やブラウザ固有の API は使えません。
// cheerio: 出力内容の検証
const $ = cheerio.load(renderedHtml);
expect($(".error-message").length).toBe(1);

domino は、DOM 構造の検証には使えますが、イベントシミュレーション機能は限定的です。

  • jsdom ほどテストエコシステムとの統合は進んでいません。
// domino: 構造検証
const doc = domino.createDocument(renderedHtml);
expect(doc.querySelectorAll(".item").length).toBe(5);

parse5 は、HTML パーサー自体のテストや、AST 変換ツールの開発に使われます。

  • アプリケーションの動作テストには通常使用しません。
// parse5: AST 構造の検証
const ast = parse5.parse(html);
// AST のノード構造が正しいか検証する

🛠️ API の使いやすさと学習コスト

開発者がどれだけ早くコードを書けるかも重要な選定基準です。

cheerio は、jQuery を知っている開発者にとって最も親しみやすいです。

  • チェーンメソッドで直感的に操作を書けます。
// cheerio: 直感的なチェーン操作
$("ul").find("li").addClass("active").text();

jsdom は、標準の Web API に準拠しているため、ブラウザでの開発経験がそのまま活かせます。

  • querySelectoraddEventListener など、普段使う API が使えます。
// jsdom: 標準 Web API
document.querySelector("ul").classList.add("active");

domino も標準 DOM API に準拠していますが、window がないため一部のコードは修正が必要です。

  • ブラウザ依存のコードをサーバーに持ってくる際に注意が必要です。
// domino: 標準 API だが window なし
doc.querySelector("ul").classList.add("active");

parse5 は、AST を直接扱うため、他の 3 つに比べて学習コストが高いです。

  • HTML 構造の深い理解が必要になります。
// parse5: AST 直接操作
// ノードを再帰的に走査する関数を書く必要がある
function traverse(node) { /*...*/ }

🌐 実世界のユースケース

シナリオ 1:Web スクレイピング

大量のページから特定のデータを抽出したい。

  • 最適: cheerio
  • 理由:高速で、必要なデータ抽出に特化した API が揃っているため。
const $ = cheerio.load(html);
const price = $(".price").text();

シナリオ 2:コンポーネントのサーバーサイドレンダリングテスト

React や Vue コンポーネントが正しくレンダリングされるか確認したい。

  • 最適: jsdom
  • 理由:ブラウザ環境をエミュレートし、フレームワークのライフサイクルを正しく動作させるため。
const { JSDOM } = require("jsdom");
global.window = new JSDOM().window;
// ここでコンポーネントをマウントしてテスト

シナリオ 3:HTML のサニタイズや変換ツール開発

HTML 構造を安全に書き換えたり、別の形式に変換したい。

  • 最適: parse5
  • 理由:パーシングとシリアライズを正確に行え、中間表現を自由に制御できるため。
const ast = parse5.parse(html);
// AST を加工して
const html = parse5.serialize(ast);

シナリオ 4:軽量な DOM 操作が必要だが jsdom は重すぎる

DOM 操作は必要だが、イベントやウィンドウ機能は不要。

  • 最適: domino
  • 理由:jsdom より軽量で、標準 DOM API が使えるため。
const doc = domino.createDocument(html);
doc.querySelector("div").remove();

📊 比較サマリーテーブル

特徴cheeriojsdomdominoparse5
主な用途スクレイピング、HTML 操作テスト、ブラウザエミュレーション軽量 DOM 操作パーシング基盤
API スタイルjQuery ライク標準 Web API標準 DOM APIAST 操作
DOM 実装独自(簡易)完全準拠準拠(window なし)なし(AST)
JavaScript 実行
イベント処理⚠️ 限定的
パフォーマンス🚀 非常に高速🐢 重い🏃 中程度🚀 高速(パーシングのみ)
メンテナンス✅ 活発✅ 活発⚠️ 低調✅ 活発

💡 最終的な推奨事項

プロジェクトの要件に応じて、以下のように選択するのが賢明です。

  • スクレイピングや単純な HTML 加工cheerio を選択。開発速度と実行速度のバランスが最も優れています。
  • ブラウザ挙動のテストや SSR テストjsdom を選択。環境の再現性が最も重要です。
  • 標準 DOM API が必要だが軽量さが欲しいdomino を検討。ただしメンテナンス状況を注視してください。
  • コンパイラや変換ツールを開発するparse5 を選択。最も低レベルで正確な制御が可能です。

これら 4 つのライブラリは互いに排他的なものではなく、状況に応じて使い分けることで、Node.js での HTML 処理を効率的かつ確実に行うことができます。

選び方: cheerio vs domino vs jsdom vs parse5

  • cheerio:

    jQuery に似た構文で HTML を操作したい場合や、スクレイピングで特定の要素を素早く抽出したい場合に選択します。ブラウザの DOM 仕様全体を必要とせず、パフォーマンスと記述のしやすさを重視するプロジェクトに適しています。

  • domino:

    ブラウザのレイアウトや描画機能を必要とせず、純粋な DOM ツリー操作だけを行いたい場合に適しています。jsdom よりも軽量ですが、メンテナンス頻度は低いため、長期プロジェクトでは注意が必要です。

  • jsdom:

    ブラウザ環境をシミュレートして JavaScript を実行する必要がある場合や、React や Vue などのフレームワークをサーバーサイドでテストする場合に選択します。DOM 仕様のサポートが最も充実していますが、リソース消費は大きめです。

  • parse5:

    HTML パーシングやシリアライズそのものを行いたい場合、あるいは独自の DOM 実装の上にパーサーを構築したい場合に使用します。DOM 操作 API は提供しないため、他のライブラリと組み合わせて使うことが一般的です。

cheerio のREADME

cheerio

The fast, flexible, and elegant library for parsing and manipulating HTML and XML.

中文文档 (Chinese Readme)

import * as cheerio from 'cheerio';
const $ = cheerio.load('<h2 class="title">Hello world</h2>');

$('h2.title').text('Hello there!');
$('h2').addClass('welcome');

$.html();
//=> <html><head></head><body><h2 class="title welcome">Hello there!</h2></body></html>

Installation

Install Cheerio using a package manager like npm, yarn, or bun.

npm install cheerio
# or
bun add cheerio

Features

❤ Proven syntax: Cheerio implements a subset of core jQuery. Cheerio removes all the DOM inconsistencies and browser cruft from the jQuery library, revealing its truly gorgeous API.

ϟ Blazingly fast: Cheerio works with a very simple, consistent DOM model. As a result parsing, manipulating, and rendering are incredibly efficient.

❁ Incredibly flexible: Cheerio wraps around parse5 for parsing HTML and can optionally use the forgiving htmlparser2. Cheerio can parse nearly any HTML or XML document. Cheerio works in both browser and server environments.

API

Loading

First you need to load in the HTML. This step in jQuery is implicit, since jQuery operates on the one, baked-in DOM. With Cheerio, we need to pass in the HTML document.

// ESM or TypeScript:
import * as cheerio from 'cheerio';

// In other environments:
const cheerio = require('cheerio');

const $ = cheerio.load('<ul id="fruits">...</ul>');

$.html();
//=> <html><head></head><body><ul id="fruits">...</ul></body></html>

Selectors

Once you've loaded the HTML, you can use jQuery-style selectors to find elements within the document.

$( selector, [context], [root] )

selector searches within the context scope which searches within the root scope. selector and context can be a string expression, DOM Element, array of DOM elements, or cheerio object. root, if provided, is typically the HTML document string.

This selector method is the starting point for traversing and manipulating the document. Like in jQuery, it's the primary method for selecting elements in the document.

$('.apple', '#fruits').text();
//=> Apple

$('ul .pear').attr('class');
//=> pear

$('li[class=orange]').html();
//=> Orange

Rendering

When you're ready to render the document, you can call the html method on the "root" selection:

$.root().html();
//=>  <html>
//      <head></head>
//      <body>
//        <ul id="fruits">
//          <li class="apple">Apple</li>
//          <li class="orange">Orange</li>
//          <li class="pear">Pear</li>
//        </ul>
//      </body>
//    </html>

If you want to render the outerHTML of a selection, you can use the outerHTML prop:

$('.pear').prop('outerHTML');
//=> <li class="pear">Pear</li>

You may also render the text content of a Cheerio object using the text method:

const $ = cheerio.load('This is <em>content</em>.');
$('body').text();
//=> This is content.

The "DOM Node" object

Cheerio collections are made up of objects that bear some resemblance to browser-based DOM nodes. You can expect them to define the following properties:

  • tagName
  • parentNode
  • previousSibling
  • nextSibling
  • nodeValue
  • firstChild
  • childNodes
  • lastChild

Screencasts

https://vimeo.com/31950192

This video tutorial is a follow-up to Nettut's "How to Scrape Web Pages with Node.js and jQuery", using cheerio instead of JSDOM + jQuery. This video shows how easy it is to use cheerio and how much faster cheerio is than JSDOM + jQuery.

Cheerio in the real world

Are you using cheerio in production? Add it to the wiki!

Sponsors

Does your company use Cheerio in production? Please consider sponsoring this project! Your help will allow maintainers to dedicate more time and resources to its development and support.

Headlining Sponsors

Tidelift Github AirBnB HasData

Other Sponsors

OnlineCasinosSpelen Nieuwe-Casinos.net

Backers

Become a backer to show your support for Cheerio and help us maintain and improve this open source project.

Vasy Kafidoff

License

MIT