JavaScriptによるウェブスクレイピング:実用的なNode.jsガイド

JavaScriptによるウェブスクレイピング

ScrapelessユニバーサルスクレイピングAPIは、認証されたHTTPリクエストを通じてフェッチされたまたはレンダリングされたページコンテンツをJavaScriptプログラムに提供する。

TL;DR

  • JavaScriptによるスクレイピングは一つのページ分類から始まる。 必要なフィールドがレスポンスボディに存在する場合はHTTPクライアントとHTMLパーサを使用し、スクリプトが後で作成する場合はブラウザレンダリングを使用する。
  • Cheerioはマークアップを解析するが、ページスクリプトは実行しない。 その境界によりCheerioはサーバーレンダリングされたページに適しており、クライアント専用コンテンツには適していない。
  • セレクタは意味を説明すべきであり、外観ではない。 安定した属性、セマンティック要素、およびスコープされた関係は、長い生成されたクラスチェーンよりも再設計に強い。
  • ページネーションには明示的な停止ルールが必要。 確認された次のリンクまたは文書化されたカーソルに従い、ソースがコレクションの終了を告げるときに停止する。
  • 生産出力にはスキーマが必要。 テキストを正規化し、URLを解決し、nullableフィールドを保持し、ストレージ前にすべてのレコードを検証する。

JavaScriptウェブスクレイピングの動作

JavaScriptによるウェブスクレイピングは、フェッチ、解析、選択、および正規化のパイプラインである。フェッチステップはHTTP経由でバイトを取得する。パーサはそれらのバイトを文書ツリーに変換する。セレクタは必要なフィールドを保持するノードを見つける。最終ステップはページ型の値を安定したレコードに変換し、アプリケーションが保存または比較できるようにする。

最初の決定は、レスポンスにすでにデータが含まれているかどうかである。ブラウザの開発者ツールを開き、ネットワークレスポンスまたはページソースを検査し、画面上で表示される値を探す。その値が返されたHTMLに表示されている場合は、軽量パーサで十分である。レスポンスがシェルのみで、値がJavaScript実行後に表示される場合、取得層はページをレンダリングするか、許可された構造化されたエンドポイントを呼び出さなければならない。

最新のNode.jsはブラウザ互換の グローバルfetchインターフェースを公開している。Fetchはレスポンスオブジェクトを返す;呼び出すことで text() HTMLを読み取る。レスポンスステータスは依然として重要である。ログインページ、同意画面、またはアクセス拒否ドキュメントは有効なHTMLであり得るので、成功した解析は正しいページが到着したことを証明するものではない。

Cheerioとブラウザの選択

Cheerioは、ターゲットコンテンツが静的HTMLに存在する場合、正しいJavaScriptパーサーである。 公式Cheerioイントロダクション は境界について明示的である:Cheerioはマークアップを解析し、jQueryのようなトラバーサルAPIを公開するが、ブラウザではなく、JavaScriptを実行せず、サブリソースを読み込まず、ページを描画しない。

ページ条件推奨パス理由
フィールドがレスポンスHTMLに表示されるfetch およびCheerio低オーバーヘッドおよび直接CSS選択
スクリプトが必要なノードを作成するレンダリングされた取得初期レスポンスにデータが含まれない
公開されたJSONレスポンスがページをサポートする文書化されたAPIまたは許可されたエンドポイント構造化データはDOMの解釈を回避する
クリックまたはスクロールが結果セットを変更するブラウザオートメーションワークフローはページの状態とイベントに依存する

ブラウザパスはより多くのメモリと起動時間を要するため、意図的な選択であるべきである。データまたはインタラクションが要求される場合にのみレンダリングする。この分離により、テストも容易になる:パーサは保存されたHTMLで運用され、取得層はネットワークとページ状態に対してテストされる。

小さな静的HTMLスクレイパーを構築する

基本的なNode.jsプロジェクトにはCheerioと現在のNodeランタイムが必要である。パッケージをインストールし、1ページを要求し、ステータスを確認し、ボディを読み込み、セレクターの作業を各繰り返しカードにスコープする。以下の例は、Example Domainから見出しと正規リンクを読み取る。それは意図的に1つの公開ページに限定されている。

import * as cheerio from 'cheerio';

const response = await fetch('https://example.com/');
if (!response.ok) {
  throw new Error(`Unexpected HTTP status: ${response.status}`);
}

const html = await response.text();
const $ = cheerio.load(html);

const record = {
  title: $('h1').first().text().trim(),
  link: new URL($('a').first().attr('href'), response.url).href,
};

console.log(JSON.stringify(record, null, 2));

セレクタはページが単純であるため短い。カタログでは、最初に繰り返し容器を選択し、その後その容器内の子ノードをクエリする。スコープは、各行がページ上の最初のタイトルまたは価格を受け取る一般的なデータ品質のバグを防ぐ。欠落フィールドは nullであるべきであり、真正な空白値と区別がつかない空の文字列ではない。

変化に強いセレクタを設計する

セレクタの耐久性はセレクタの巧妙さよりも重要である。安定した識別子、文書化されたデータ属性、セマンティック関係、または耐久性のあるURL形状を持つ要素を好む。ブラウザインスペクタからコピーされたセレクタは、レイアウトラッパーや内容モデルを変更せずに変更される生成されたクラス名を含む可能性がある。

その セレクタレベル4仕様 ブラウザやパーサーツールで使用されるCSSセレクタモデルを定義します。実際には、安全なサブセットは通常シンプルです:フィールドの属性セレクタ、カードにスコープされた子孫セレクタ、および階層に意味がある場合の直接子セレクタ。位置そのものがソース契約の一部でない限り、位置セレクタは避けてください。

  • 各レコードを繰り返しコンテナに固定します。 ノードに対して、ドキュメント全体をループ内で検索するのではなく、タイトル、価格、およびリンクを抽出します。
  • 相対URLをすぐに解決します。 最終応答URLに対して絶対URLを構築し、リダイレクトやネストされたパスが後のフェッチを乱さないようにします。
  • スキーマが要求するものだけを正規化します。 周囲の空白をトリムし、既知の数値形式を解析しますが、解釈が不確かである場合は元のテキストを保持します。
  • ページの識別を確認します。 行を受け入れる前に見出し、正規URL、または既知の構造マーカーを確認します。

ページネーションとページ状態を処理します。

JavaScriptスクレイピングのページネーションは、ソース自身の継続信号に従うべきです。ページ番号の場合、次のリンクを抽出して解決します。カーソルベースの応答の場合、データとともに返されたカーソルを保持します。無限リストの場合、ブラウザワークフローには、制御が無効になった、アイテム数が変更されていない、または明示的な終了マーカーなどの測定可能な完了条件が必要です。

空の結果がコレクションの終了を意味するとは考えないでください。空の行は、間違ったロケールや同意の間に表示されるインタースティシャル、変更されたセレクタ、またはクライアントレンダリングシェルを意味することもあります。各フェッチに軽量の診断を保存してください:最終URL、ステータス、コンテンツタイプ、ページ識別チェック、および一致したコンテナの数。これらの値は、完全なページボディをログに置かずにゼロ行の結果を説明します。

抽出された値を信頼できるレコードに変換します。

JavaScriptスクレイパーは、抽出と正規化が別の関数であるときに信頼性があります。抽出はページが言っていることを読み取ります。正規化はそのテキストをアプリケーションスキーマにマッピングします。境界をはっきりさせておくことで、セレクタコードが静かにビジネス上の決定を下すことを防ぎます。たとえば、「利用不可」を数値ゼロとして扱ったり、誤ったルールで地域の小数形式を変換したりすることです。

セレクタを書く前に、必要なフィールドとオプションのフィールドを定義します。識別フィールドがない場合は、レコードを拒否します。オプションフィールドを保持しますが、 null. 安定したソースキーまたは正規URLを使用して重複を排除し、変化するタイトルではなく、ストレージ層に取得タイムスタンプを追加します。

パイプラインをスケールアップする前にテストします。

パーサーテスト用に保存されたフィクスチャから始めます。通常のページ用の代表的なHTMLファイル、欠落しているオプションフィールド用のもの、および識別チェックに失敗するべきものを1つずつ保持します。これらのフィクスチャにより、セレクタの変更をレビュー可能にし、パーサーテストをネットワークの可用性に依存しないものに保ちます。

小さな公共ターゲットに対して別々に取得をテストします。最終URL、ステータスクラス、および期待されるマーカーを確認します。 HTTPセマンティクス仕様 は、ステータスコードが応答を説明するが、本文が期待されたビジネスページであることを証明できない理由を説明します。有効な200応答は、同意またはアカウントページである可能性があります。

作業負荷が増加する場合、ホストごとに制約された同時実行性を持ち、キューを観察可能に保ちます。受け入れたレコード、拒否されたレコード、予期しないページの識別、およびセレクタのミスを測定します。間違ったページを保存する速いスクレイパーは、はっきり失敗する遅いものよりも悪いです。

結論

JavaScriptによるウェブスクレイピングは、トランスポート決定がセレクタ作業の前に行われるときが最も効果的です。 fetch とCheerioを使用して応答HTMLを取得し、ページスクリプトやインタラクションが必要な状態を作成する場合のみレンダリングし、抽出と正規化を別に保ちます。その結果、システムが小さくなり、明確な失敗信号と、ソースレイアウトが変更されても便利なテストが残ります。

JavaScriptデータワークフローを構築する準備はできましたか?

Node.js取得レイヤーをScrapelessに接続し、既存のセレクタを保持し、1つの制約された公共データワークフローをエンドツーエンドで検証します。

今すぐサインアップして $5の無料クレジットを受け取りますクレジットカードは不要です.

あなたの$5クレジットを獲得してください →

FAQ

JavaScriptはブラウザなしでウェブサイトをスクレイプできますか?

はい。JavaScriptは、HTTPクライアントとCheerioなどのHTMLパーサーを使用してサーバーレンダリングされたページをスクレイプできます。必要なコンテンツがページスクリプトによって生成されるか、インタラクションに依存する場合はブラウザが必要になります。

Cheerioは、画面上に表示されているコンテンツに対して要素を返さないのはなぜですか?

Cheerioは、受け取ったHTMLからそのノードが存在しない場合、要素を返しません。ページソースをライブDOMと比較します。スクリプトがノードを作成する場合は、レンダリングされた取得または許可された構造ソースを使用します。

JavaScriptスクレイパーはCSSセレクタを使用すべきですか、それともXPathを使用すべきですか?

CSSセレクタは通常、Node.jsパーサーやブラウザAPIでの実用的なデフォルトです。XPathは関係の多いクエリを表現できますが、セレクタの安定性と明確なスコープの方がクエリ言語よりも重要です。

JavaScriptスクレイパーは変更されたマークアップをどのように処理すべきですか?

JavaScriptスクレイパーは、明示的な構造チェックに失敗し、小さな診断をキャプチャし、セレクタの更新を要求する必要があります。ゼロの一致を成功した空のページとして扱うと、破損を隠し、有効な下流データを消去する可能性があります。

JavaScriptによるウェブスクレイピングは合法ですか?

JavaScriptによるウェブスクレイピングは、1つの普遍的なルールに支配されていません。収集は、許可された公共データに制限し、適用される法律やサイトの条件を確認し、アクセス制御を尊重し、敏感または影響が大きい使用ケースについて法的助言を求めます。

参照