cheerio、htmlparser2、sax、xml2js は、Node.js 環境で構造化マークアップ(HTML や XML)を処理するための代表的なライブラリです。cheerio は jQuery に似た構文で HTML を操作し、htmlparser2 は高性能なストリーミングパーサーを提供します。sax は XML 専用のストリーミングパーサーであり、xml2js は XML を JavaScript オブジェクトに変換することに特化しています。これらはそれぞれ「DOM 操作」「低レベルパース」「データバインディング」という異なる層の問題を解決します。
cheerio、htmlparser2、sax、xml2js は、Node.js 環境で構造化マークアップ(HTML や XML)を処理するための代表的なライブラリですが、それぞれ役割とアプローチが異なります。cheerio は DOM 操作に、htmlparser2 と sax はストリーミングパースに、xml2js はオブジェクト変換に特化しています。実務でどのツールを選ぶべきか、技術的な違いを深掘りして比較します。
各ライブラリは、データへのアクセス方法が根本的に異なります。目的に応じて適切な抽象化レベルを選ぶ必要があります。
cheerio は、jQuery に似たチェーン可能な API を提供します。
// 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 オブジェクトに変換します。
// 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 も同様にストリーミングに対応しています。
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 もイベントベースなので状態管理が必要です。
// 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];
});
扱うデータフォーマットによって、選択肢が狭まります。
cheerio は HTML に最適化されています。
// cheerio: Tolerant HTML parsing
const $ = cheerio.load('<div><p>Unclosed'); // Works fine
htmlparser2 は HTML と XML の両方を扱えます。
// htmlparser2: Configurable mode
const parser = new Parser({ xmlMode: true });
sax は XML 専用です。
// sax: Strict XML only
// <div>Unclosed</div> would cause error in strict mode
xml2js は XML 専用です。
// xml2js: XML focused
// Not suitable for malformed HTML
異なるアプローチを取っていますが、根底にある思想や共通する機能もあります。
htmlparser2、sax、xml2js は Node.js の Stream API と連携できます。// All support piping from streams (conceptually)
fs.createReadStream('file.xml').pipe(parserStream);
htmlparser2、sax)はイベント emitting です。// Event listeners pattern
parser.on('opentag', handler);
stream.on('data', handler);
xml2js と sax は XML エラーに厳格です。// Error handling
parser.on('error', (err) => console.error(err));
| 特徴 | 共通する機能 |
|---|---|
| 環境 | 🟢 Node.js ネイティブ対応 |
| 処理 | 🟢 非同期・イベント駆動 |
| 入力 | 🟢 文字列またはストリーム |
| 用途 | 🟢 構造化データ抽出 |
| 機能 | cheerio | htmlparser2 | sax | xml2js |
|---|---|---|---|---|
| 主用途 | 🎨 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 を選んでください。それぞれの道具は、異なる「層」の問題を解決するために存在しています。
サーバーサイドで HTML をスクレイピングしたり、jQuery のような直感的な構文で DOM 操作が必要な場合に選択します。Web サイトのデータ抽出や、HTML テンプレートの変換タスクに最適です。
HTML または XML を高速にストリーミング処理したい場合や、パーシング過程のイベント(タグ開始、テキストなど)を細かく制御したい場合に選択します。メモリ効率が重要な大容量データ処理に適しています。
厳密な XML 準拠が必要なレガシーシステムや、XML 専用のストリーミング処理を低レベルで実装する場合に選択します。ただし、最近はよりモダンな代替案も検討すべきです。
XML データを直接 JavaScript のオブジェクトや JSON 形式に変換して扱いたい場合に選択します。設定ファイルの読み込みや、XML API のレスポンスを構造化データとして利用する際に便利です。
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>
Install Cheerio using a package manager like npm, yarn, or bun.
npm install cheerio
# or
bun add cheerio
❤ 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.
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>
Once you've loaded the HTML, you can use jQuery-style selectors to find elements within the document.
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
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.
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:
tagNameparentNodepreviousSiblingnextSiblingnodeValuefirstChildchildNodeslastChildThis 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.
Are you using cheerio in production? Add it to the wiki!
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
Other Sponsors
Become a backer to show your support for Cheerio and help us maintain and improve this open source project.
MIT