web-dev-qa-db-ja.com

Node.jsおよびXPathを使用したページのパフォーマンス解析

Node.jsを使用したWebスクレイピングに取り組んでいます。いくつかの種類のGUIで半自動でXPathを生成できるため、XPathを使用したいと思います。問題は、これを効果的に行う方法が見つからないことです。

  1. jsdomは非常に遅いです。 CPU負荷がフルで、メモリフットプリントが重い1分程度で500KiBファイルを解析しています。
  2. HTML解析用の一般的なライブラリ(例:cheerio)は、XPathをサポートせず、W3C準拠のDOMも公開しません。
  3. 効果的なHTML解析は明らかにWebKitに実装されているため、phantomまたはcasperを使用することはオプションですが、node <script>だけでなく、特別な方法で実行する必要があります。この変更によって暗示されるリスクに頼ることはできません。たとえば、phantomnode-inspectorを実行する方法を見つけるのははるかに困難です。
  4. Spookyはオプションですが、 バギーで十分 なので、私のマシンではまったく実行されませんでした。

XPathでHTMLページを解析する正しい方法は何ですか?

29
polkovnikov.ph

これはいくつかの手順で実行できます。

  1. parse5を使用してHTMLを解析します。悪い点は、結果がDOMではないことです。それは十分に高速でW3Cに準拠していますが。
  2. 入力としてparse5のDOMのような構造を受け入れるxmlserializerでXHTMLにシリアル化します。
  3. そのXHTMLをxmldomで再度解析します。これでようやくDOMができました。
  4. 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);
})();
35
pda

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 のようなものを使用してください。

13
mb21

npm install htmlstrip-native これは、 ネイティブ実装 を使用して、関連するHTMLパーツを解析および抽出します。純粋なjs実装の50倍高速であると主張しています(その主張を検証していません)。

ニーズに応じて、html-stripを直接使用するか、コードとバインディングを解除して、htmlstrip-nativeで内部的に使用されるC++を所有できます。

Xpathを使用する場合は、ここで既に利用可能なラッパーを使用します。 https://www.npmjs.org/package/xpath

1
Soren

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();
    });
1
rchipka

HTMLページを解析する正しい方法はないかもしれません。 Webのスクレイピングとクロールに関する非常に最初のレビューでは、 Scrapy があなたのニーズの良い候補になることがわかりました。 CSSセレクターとXPathセレクターの両方を受け入れます。 Node.jsの領域には、かなり新しいモジュール node-osmosis があります。このモジュールはlibxmljs上に構築されているため、CSSとXPathの両方をサポートすることになっていますが、XPathを使用した例は見つかりませんでした。

0
pateheo