Node.jsを使用したWebスクレイピングに取り組んでいます。いくつかの種類のGUIで半自動でXPathを生成できるため、XPathを使用したいと思います。問題は、これを効果的に行う方法が見つからないことです。
jsdom
は非常に遅いです。 CPU負荷がフルで、メモリフットプリントが重い1分程度で500KiBファイルを解析しています。cheerio
)は、XPathをサポートせず、W3C準拠のDOMも公開しません。phantom
またはcasper
を使用することはオプションですが、node <script>
だけでなく、特別な方法で実行する必要があります。この変更によって暗示されるリスクに頼ることはできません。たとえば、phantom
でnode-inspector
を実行する方法を見つけるのははるかに困難です。Spooky
はオプションですが、 バギーで十分 なので、私のマシンではまったく実行されませんでした。XPathでHTMLページを解析する正しい方法は何ですか?
これはいくつかの手順で実行できます。
parse5
を使用してHTMLを解析します。悪い点は、結果がDOMではないことです。それは十分に高速でW3Cに準拠していますが。parse5
のDOMのような構造を受け入れるxmlserializer
でXHTMLにシリアル化します。xmldom
で再度解析します。これでようやくDOMができました。xpath
ライブラリはxmldom
に基づいて構築され、XPathクエリを実行できます。 XHTMLには独自の名前空間があり、//a
などのクエリは機能しないことに注意してください。最後に、このようなものを取得します。
const fs = require('mz/fs');
const xpath = require('xpath');
const parse5 = require('parse5');
const xmlser = require('xmlserializer');
const dom = require('xmldom').DOMParser;
(async () => {
const html = await fs.readFile('./test.htm');
const document = parse5.parse(html.toString());
const xhtml = xmlser.serializeToString(document);
const doc = new dom().parseFromString(xhtml);
const select = xpath.useNamespaces({"x": "http://www.w3.org/1999/xhtml"});
const nodes = select("//x:a/@href", doc);
console.log(nodes);
})();
Libxmljs は、XPath 1.0クエリをサポートする LibXML Cライブラリへのバインディングのみであるため、現在、最速の実装です(何か ベンチマークなど )。
var libxmljs = require("libxmljs");
var xmlDoc = libxmljs.parseXml(xml);
// xpath queries
var gchild = xmlDoc.get('//grandchild');
ただし、最初にHTMLをサニタイズし、適切なXMLに変換する必要があります。そのためには、 HTMLTidy コマンドラインユーティリティ(tidy -q -asxml input.html
)、またはノードのみを保持したい場合は、 xmlserializer のようなものを使用してください。
npm install htmlstrip-native
これは、 ネイティブ実装 を使用して、関連するHTMLパーツを解析および抽出します。純粋なjs実装の50倍高速であると主張しています(その主張を検証していません)。
ニーズに応じて、html-stripを直接使用するか、コードとバインディングを解除して、htmlstrip-nativeで内部的に使用されるC++を所有できます。
Xpathを使用する場合は、ここで既に利用可能なラッパーを使用します。 https://www.npmjs.org/package/xpath
Osmosis はあなたが探しているものだと思います。
- ネイティブのlibxml Cバインディングを使用します
- CSS 3.0およびXPath 1.0セレクターハイブリッドをサポート
- シズルセレクター、スリックセレクターなど
- JQuery、cheerio、jsdomなどの大きな依存関係はありません
HTMLパーサー機能
- 高速解析
- 非常に高速な検索
- 小さなメモリフットプリント
HTML DOM機能
- Ajaxコンテンツの読み込みと検索
- DOMインタラクションとイベント
- 埋め込みスクリプトとリモートスクリプトを実行する
- DOMでコードを実行する
osmosis.get(url)
.find('//div[@class]/ul[2]/li')
.then(function () {
count++;
})
.done(function () {
assert.ok(count == 2);
assert.done();
});
HTMLページを解析する正しい方法はないかもしれません。 Webのスクレイピングとクロールに関する非常に最初のレビューでは、 Scrapy があなたのニーズの良い候補になることがわかりました。 CSSセレクターとXPathセレクターの両方を受け入れます。 Node.jsの領域には、かなり新しいモジュール node-osmosis があります。このモジュールはlibxmljs上に構築されているため、CSSとXPathの両方をサポートすることになっていますが、XPathを使用した例は見つかりませんでした。