cheerio vs htmlparser2 vs sax vs xml2js
Node.js における HTML/XML パースとデータ抽出戦略
cheeriohtmlparser2saxxml2js類似パッケージ:

Node.js における HTML/XML パースとデータ抽出戦略

cheeriohtmlparser2saxxml2js は、Node.js 環境で構造化マークアップ(HTML や XML)を処理するための代表的なライブラリです。cheerio は jQuery に似た構文で HTML を操作し、htmlparser2 は高性能なストリーミングパーサーを提供します。sax は XML 専用のストリーミングパーサーであり、xml2js は XML を JavaScript オブジェクトに変換することに特化しています。これらはそれぞれ「DOM 操作」「低レベルパース」「データバインディング」という異なる層の問題を解決します。

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

3 年

GitHub Starsランキング

統計詳細

パッケージ
ダウンロード数
Stars
サイズ
Issues
公開日時
ライセンス
cheerio030,3841.01 MB465ヶ月前MIT
htmlparser204,768235 kB43ヶ月前MIT
sax01,15661 kB963ヶ月前BlueOak-1.0.0
xml2js04,9663.44 MB2483年前MIT

Node.js における HTML/XML パースとデータ抽出:cheerio vs htmlparser2 vs sax vs xml2js

cheeriohtmlparser2saxxml2js は、Node.js 環境で構造化マークアップ(HTML や XML)を処理するための代表的なライブラリですが、それぞれ役割とアプローチが異なります。cheerio は DOM 操作に、htmlparser2sax はストリーミングパースに、xml2js はオブジェクト変換に特化しています。実務でどのツールを選ぶべきか、技術的な違いを深掘りして比較します。

🎨 API デザイン:DOM 操作 vs イベントストリーム vs オブジェクト変換

各ライブラリは、データへのアクセス方法が根本的に異なります。目的に応じて適切な抽象化レベルを選ぶ必要があります。

cheerio は、jQuery に似たチェーン可能な API を提供します。

  • HTML 文字列を読み込んで DOM ツリーを構築します。
  • CSS セレクターを使って要素を検索・操作できます。
// cheerio: jQuery-like DOM manipulation
const cheerio = require('cheerio');
const $ = cheerio.load('<html><title>Test</title></html>');
const title = $('title').text();
console.log(title); // "Test"

htmlparser2 は、イベント駆動型の低レベルパーサーです。

  • タグが開いた時、テキストが来た時などのイベントをフックします。
  • 全データをメモリに載せないで処理できます。
// htmlparser2: Event-based streaming
const { Parser } = require('htmlparser2');
const parser = new Parser({
  onopentag: (name) => console.log(`Start: ${name}`),
  ontext: (text) => console.log(`Text: ${text}`)
});
parser.write('<html><title>Test</title></html>');
parser.end();

sax は、XML 専用のストリーミングパーサーです。

  • htmlparser2 に似ていますが、XML 仕様に厳格です。
  • 名前空間や属性の処理を細かく制御できます。
// sax: Strict XML streaming
const sax = require('sax');
const stream = sax.createStream(true);
stream.on('opentag', (node) => console.log(`Tag: ${node.name}`));
stream.write('<root><item>Test</item></root>');
stream.end();

xml2js は、XML を JavaScript オブジェクトに変換します。

  • パース結果をそのままオブジェクトとして扱えます。
  • コールバックまたは Promise で結果を受け取ります。
// xml2js: XML to Object conversion
const xml2js = require('xml2js');
const parser = new xml2js.Parser();
parser.parseString('<root><item>Test</item></root>', (err, result) => {
  console.log(result.root.item[0]); // "Test"
});

🌊 ストリーミング処理:大容量データの扱い

ファイルを逐次読み込む場合や、ネットワークストリームを処理する場合、メモリ効率が決定的な要因になります。

cheerio は基本的に全体をメモリに読み込みます。

  • cheerio.load() に文字列全体を渡す必要があります。
  • 大きなファイルではメモリ圧迫のリスクがあります。
// cheerio: Requires full string in memory
const html = fs.readFileSync('large-file.html', 'utf8');
const $ = cheerio.load(html); // All in memory

htmlparser2 はチャンク単位で処理できます。

  • write() メソッドでデータを少しずつ流し込めます。
  • 数ギガバイトのファイルでも安定して動作します。
// htmlparser2: Chunked streaming
const parser = new Parser({ ontext: (t) => {} });
stream.on('data', (chunk) => parser.write(chunk));
stream.on('end', () => parser.end());

sax も同様にストリーミングに対応しています。

  • XML データをストリームから逐次パースできます。
  • htmlparser2 よりも XML 仕様に忠実です。
// sax: XML streaming
const stream = sax.createStream(true);
fs.createReadStream('data.xml').pipe(stream);

xml2js は通常全体を読み込みますが、ストリーム対応も可能です。

  • 基本は parseString で全体を渡します。
  • xml2js.Parser をストリームに繋ぐこともできますが、設定が必要です。
// xml2js: Typically bulk, but can stream
const parser = new xml2js.Parser();
fs.createReadStream('data.xml').pipe(parser);
parser.on('end', (result) => console.log(result));

🎯 データ抽出:目的の値を取得する方法

実際に必要なデータを取り出す際の手間も、開発速度に影響します。

cheerio は CSS セレクターで直感的に取得できます。

  • 複雑なネストも .find().children() で辿れます。
  • スクレイピング作業が非常に捗ります。
// cheerio: CSS Selector extraction
const $ = cheerio.load(html);
const price = $('.product .price').text();

htmlparser2 は状態管理を自分で行う必要があります。

  • 目的のタグが来たフラグを立てて、次のテキストイベントを拾います。
  • 柔軟ですが、コード量は増えます。
// htmlparser2: Manual state tracking
let capture = false;
const parser = new Parser({
  onopentag: (name) => { if(name === 'price') capture = true; },
  ontext: (text) => { if(capture) console.log(text); }
});

sax もイベントベースなので状態管理が必要です。

  • XML の構造を理解した上でイベントをハンドリングします。
  • 厳密な検証しながらデータを拾えます。
// sax: Event handling with state
let target = false;
const stream = sax.createStream(true);
stream.on('opentag', (n) => { if(n.name === 'price') target = true; });
stream.on('text', (t) => { if(target) console.log(t); });

xml2js はオブジェクトプロパティとしてアクセスできます。

  • パース済みのオブジェクトから値を取るだけです。
  • 構造が固定されている場合に最も楽です。
// xml2js: Object property access
parser.parseString(xml, (err, res) => {
  const price = res.product.price[0];
});

🌐 HTML と XML の互換性

扱うデータフォーマットによって、選択肢が狭まります。

cheerio は HTML に最適化されています。

  • 壊れた HTML も許容してパースします(タグ閉じ忘れなど)。
  • XML モードもありますが、主用途は HTML です。
// cheerio: Tolerant HTML parsing
const $ = cheerio.load('<div><p>Unclosed'); // Works fine

htmlparser2 は HTML と XML の両方を扱えます。

  • オプションで XML モードに切り替え可能です。
  • 汎用性が高いパーサーです。
// htmlparser2: Configurable mode
const parser = new Parser({ xmlMode: true });

sax は XML 専用です。

  • HTML のような曖昧な構文はエラーになります。
  • 厳密な XML 処理に適しています。
// sax: Strict XML only
// <div>Unclosed</div> would cause error in strict mode

xml2js は XML 専用です。

  • XML 構造を JS オブジェクトにマップします。
  • HTML 処理には向きません。
// xml2js: XML focused
// Not suitable for malformed HTML

🤝 共通点:構造化データの処理

異なるアプローチを取っていますが、根底にある思想や共通する機能もあります。

1. 📦 Node.js ストリームとの親和性

  • htmlparser2saxxml2js は Node.js の Stream API と連携できます。
  • ファイルシステムやネットワークレスポンスを直接処理可能です。
// All support piping from streams (conceptually)
fs.createReadStream('file.xml').pipe(parserStream);

2. 🛠️ イベント駆動アーキテクチャ

  • 低レベルパーサー(htmlparser2sax)はイベント emitting です。
  • 非同期処理との相性が良く、バックプレッシャー制御も可能です。
// Event listeners pattern
parser.on('opentag', handler);
stream.on('data', handler);

3. ✅ エラーハンドリングの仕組み

  • すべて何らかのエラー通知機構を持っています。
  • xml2jssax は XML エラーに厳格です。
// Error handling
parser.on('error', (err) => console.error(err));

📊 summary: 主要な類似点

特徴共通する機能
環境🟢 Node.js ネイティブ対応
処理🟢 非同期・イベント駆動
入力🟢 文字列またはストリーム
用途🟢 構造化データ抽出

🆚 比較サマリー:主要な違い

機能cheeriohtmlparser2saxxml2js
主用途🎨 HTML DOM 操作⚙️ 低レベルパース⚙️ XML パース🔄 XML→OBJ 変換
API 形式🧩 jQuery 風📡 イベント📡 イベント📦 オブジェクト
ストリーミング❌ 基本全体読み込み✅ 完全対応✅ 完全対応⚠️ 可能だが主機能ではない
HTML 耐性✅ 高い(壊れた HTML も OK)✅ 高い❌ 低い(XML 厳格)❌ 低い(XML 専用)
出力形式🌳 DOM ツリー📝 イベントコールバック📝 イベントコールバック🗂️ JS オブジェクト

💡 全体像と推奨事項

cheerio は、Web スクレイピングや HTML 加工ツールを作る際の「標準装備」です 🧰。jQuery の知識が活かせるため、学習コストが低く、開発速度が速いです。HTML の欠けや汚れに強いのも実務では大きな利点です。

htmlparser2 は、パフォーマンスと制御性が最優先される場合の「エンジン」です ⚙️。Cheerio の内部でも使われていることがあり、より軽量な処理やカスタムロジックが必要な時に真価を発揮します。

sax は、厳密な XML 処理が必要なレガシー環境や、特定の XML 仕様に対応する必要がある場合に役立ちます 📜。ただし、新規プロジェクトでは fast-xml-parser などのモダンな代替も検討する価値があります。

xml2js は、設定ファイルや XML API のレスポンスを、すぐにコードで扱えるオブジェクトにしたい時に最適です 📦。変換コストを払ってでも、その後の処理を楽にしたい場合に選択します。

最終的なアドバイス:HTML を扱うなら cheerio、XML をオブジェクトにしたいなら xml2js、それ以外の特殊なパース要件(超大容量、独自フォーマットなど)があるなら htmlparser2 または sax を選んでください。それぞれの道具は、異なる「層」の問題を解決するために存在しています。

選び方: cheerio vs htmlparser2 vs sax vs xml2js

  • cheerio:

    サーバーサイドで HTML をスクレイピングしたり、jQuery のような直感的な構文で DOM 操作が必要な場合に選択します。Web サイトのデータ抽出や、HTML テンプレートの変換タスクに最適です。

  • htmlparser2:

    HTML または XML を高速にストリーミング処理したい場合や、パーシング過程のイベント(タグ開始、テキストなど)を細かく制御したい場合に選択します。メモリ効率が重要な大容量データ処理に適しています。

  • sax:

    厳密な XML 準拠が必要なレガシーシステムや、XML 専用のストリーミング処理を低レベルで実装する場合に選択します。ただし、最近はよりモダンな代替案も検討すべきです。

  • xml2js:

    XML データを直接 JavaScript のオブジェクトや JSON 形式に変換して扱いたい場合に選択します。設定ファイルの読み込みや、XML 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