Rustによるウェブスクレイピング: reqwest、scraper、およびTokio

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

Scrapeless Universal Scraping APIは、従来の認証されたHTTPリクエストを通じてRustクライアントに取得またはレンダリングされたHTMLを提供します。

要約

  • Rustはエラーパスをプログラムの形状の一部にします。 HTTPの失敗、欠落フィールド、無効なセレクター、出力変換は、静かな空の値の代わりに明示的な結果として表現できます。
  • reqwestは輸送を処理し、scraperはHTMLを処理します。 クレートは別々の仕事を持ち、ページがレンダリングを必要とする場合、取得を置き換え可能に保ちます。
  • Tokioは制限された同時リクエストをサポートします。 共有クライアントと制御されたタスクセットは、発見を無制限のファンアウトに変えずにスループットを向上させます。
  • セレクターは一度コンパイルすべきです。 記録ループの前にCSSセレクターを解析し、セレクターが無効な場合は起動エラーを返します。
  • マッチがゼロの場合は診断が必要です。 クライアントがレンダリングしたシェル、間違ったページのアイデンティティ、または変更されたマークアップは、すべてレコードがない有効なHTMLを生成できます。

Rustが価値を加える場所

Rustによるウェブスクレイピングは、予測可能なメモリ使用、明示的な失敗、そして制御された同時性が迅速な対話型実験よりも重要な無人収集者に適しています。Rust自体がセレクターをより正確にするわけではありません。ネットワーク、解析、ストレージの境界を無視するのが難しくします。

一般的なスタックはHTTP用のreqwest、HTML解析とCSS選択用のscraper、非同期ランタイム用のTokioです。 reqwestのドキュメント は、接続プーリングからプログラムが恩恵を受けるように、複数のリクエストを行う際にクライアントを再利用することを推奨しています。それは、タスク間で共有された構成済みクライアントを持つクローラーサービスに自然にマッピングされます。

パーサーを輸送から独立させます。型情報を持つレコードを受け取り &str 返す関数は、保存されたHTMLに対してテストできます。その後、ネットワーク関数は、サーバーのHTML、レンダリングされたドキュメント、またはフィクスチャを返すことができ、抽出ロジックを変更することはありません。

Rustスクレイピングスタックをマップする

関心Rustの選択デザインノート
HTTPreqwestクライアントクライアントを再利用し、データを読み取る前にステータスを確認する
HTMLscraperクレートドキュメントツリーを解析し、CSSセレクターでクエリを実行する
非同期ランタイムTokio制限されたネットワークタスクを駆動する
レコードStructsとserde必須およびオプションフィールドを可視化する
検証Resultおよびカスタムエラー間違ったページやあり得ないマッチ数を拒否する

パーサークレートは、マークアップを任意のテキストとして扱うのではなく、HTML解析モデルに基づいて構築されています。 HTML解析仕様 は、ドキュメントツリーがリテラルタグの順序と異なる理由を説明します: パーサーは不正なネストを修復し、定義されたルールの下で要素を推論します。

型付きRustエクストラクターを作成する

このコードは、Rustが現在のワークスペースにインストールされていないため、ローカルランタイムの前提条件です。構造は、現在のreqwestおよびscraperのAPIに従います: フェッチ、予期しないステータスをエラーに変換、テキストを読み取り、ドキュメントを解析し、その後フィールドを選択します。reqwest、scraper、Tokio、serde、およびserde_jsonを使用してCargoプロジェクトにコンパイルします。

use scraper::{Html, Selector};
use serde::Serialize;

#[derive(Serialize)]
struct Record {
    title: String,
    href: Option<String>,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = reqwest::Client::builder()
        .timeout(std::time::Duration::from_secs(20))
        .build()?;

    let html = client
        .get("https://example.com/")
        .send()
        .await?
        .error_for_status()?
        .text()
        .await?;

    let document = Html::parse_document(&html);
    let title_selector = Selector::parse("h1")?;
    let link_selector = Selector::parse("a")?;

    let title = document
        .select(&title_selector)
        .next()
        .map(|node| node.text().collect::<String>())
        .ok_or("missing page heading")?;

    let href = document
        .select(&link_selector)
        .next()
        .and_then(|node| node.value().attr("href"))
        .map(str::to_owned);

    println!("{}", serde_json::to_string_pretty(&Record { title, href })?);
    Ok(())
}

セレクターは一度解析され、抽出の前に行われます。見出しの欠如はエラーになります。これはこの例におけるページのアイデンティティフィールドだからです。リンクはオプションであるため、 Option<String>を使用します。その区別により型システムがデータ契約の一部を持ち運ぶことができます。

ページ失敗を明示的に表現する

Rustのスクレーパーは、輸送失敗、HTTPステータスの未成功、予期しないコンテンツタイプ、間違ったページの識別、セレクタの不一致を区別する必要があります。これらの状態を空のベクターに統合すると、パイプラインを修復するために必要な情報が失われます。カスタムエラー列挙型を使用すると、元のエラーをコンテキストとして保持しながら、これらのカテゴリをマシン読み取り可能に保つことができます。

その HTTPセマンティクス仕様 は応答ステータスクラスを定義していますが、成功ステータスは期待されるビジネス文書が到着することを保証するものではありません。繰り返し行を解析する前に最終URLと構造マーカーを確認してください。受け入れたカウントと拒否したカウントを別々に記録します。

  • 起動時にセレクタ文字列をコンパイルします。 無効な構文は、ワーカーがジョブを受け入れることを妨げる必要があります。
  • 識別フィールドは必須として扱います。 安定したソースキーがないレコードはストレージに到達すべきではありません。
  • オプションとしてオプショナル値を保持します。 価格、著者、またはタイムスタンプが欠如している場合は、空の文字列とは区別して残るべきです。
  • 文書のサイズを意図的に制限します。 大きなレスポンスは、期待されるページクラスに関連付けられた取得制限が必要です。

Tokioの同時実行を制御する

Tokioはネットワークの待機を重複させることを可能にしますが、スクレイピングジョブは依然として固定予算が必要です。セマフォ、バッファードストリーム、またはワーカーキューを使用して、ホストごとのアクティブなリクエストを制限できます。クライアントは内部プールを共有しつつ安価に複製されるべきです。タスクセットは設計上束縛されるべきです。

各タスクは、ソースURLとレコードまたはカテゴリ化された失敗のいずれかを含む構造化された結果を返します。その結果を一つのコーディネーターを通じて収集することで、ストレージ書き込みとメトリクスを秩序立てて保ちます。また、切り離されたタスクが会計経路の外で失敗するのを防ぎます。

発見を制限します。スコープルールなしで全てのリンクを追従するクローラーは、意図されたサイトを離れたり、代替URL形式を再訪したり、停止条件なしに成長したりする可能性があります。許可されたURLを正規化し、パスパターンを制限し、訪問された識別を保存します。

JavaScript境界を検出する

reqwestはサーバーの応答をダウンロードしますが、ページスクリプトは実行しません。スクレーパークレートは受け取ったボディを解析します。ブラウザがページソースに表示されないレコードを表示する場合、Rustコードは両方の作業に成功し、ゼロマッチを返すことがあります。その結果は能力の不一致であり、必ずしもセレクタのバグではありません。

レンダリングされた取得は、同じパーサーにポストスクリプト文書を返すことで不一致を解決します。分割を可視化します:一つの関数が忠実なHTMLを取得し、別の関数がHTMLを型付けされたレコードに変換します。この設計は、ブラウザの懸念が正規化およびストレージコードを通じて広がるのを防ぎます。

ソースルール内で操作します

Rustクローラーをスケジュールする前に、許可されたホスト、パス、データクラス、リクエスト予算を定義します。条件および適用法を確認します。その ロボット排除プロトコル は標準化されたクローラーディレクティブを提供しますが、許可、プライバシー分析、または契約審査の代わりにはなりません。

可観測性は正確性に焦点を当てるべきです:応答クラス、ページの識別、解析の持続時間、コンテナの数、受け入れられたレコード、およびカテゴリ化された失敗。普通のログに全応答ボディを保存するのは避けてください。フィクスチャは制御されたテストデータに属し、敏感な値はクローラーの診断表面の外に所属します。

系統を型付けられたレコードの隣に保ちます

型付けされた出力は系統の必要性を取り除きません。各レコードまたはバッチの隣に標準のソースURL、取得時刻、パーサーの改訂、コンパクトなページアイデンティティの結果を保存します。これらのフィールドは、下流のシステムがセレクタの変更や異なる地域のページから真の値の変化を区別できるようにします。

正規化が意味を失う可能性がある場合は、生のテキストを利用可能に保ちます。通貨文字列、ローカライズされた数字、可用性ラベル、および人間の日時にはしばしばソース特有のルールが必要です。良好なRustモデルは、正規化されたフィールドと変換を監査するために十分な元のコンテキストの両方を保持します。バリデーションは、アプリケーションが必要とする場合に通貨がない数値金額のような不可能な組み合わせをシリアル化の前に拒否できます。

スキーマの進化は意図的であるべきです。オプションのフィールドを最初に追加し、コンシューマを更新し、それから元のソースとパイプラインが一貫して存在することを証明した後にフィールドを必須にします。このアプローチは、サードパーティのマークアップが安定していると仮定することなく、Rustの型システムをデータ契約として使用します。

結論

Rustによるウェブスクレイピングは、収集者が明示的なエラーハンドリングと制御されたリソース予算で長期間実行する必要がある場合に適しています。reqwestクライアントを再利用し、セレクタを一度解析し、欠如をオプションで表現し、Tokioタスクを制限します。クライアントサイドのJavaScriptがデータを所有している場合は、型付けされたパーサーを書き直すのではなく、HTMLの取得方法を変更します。

レンダリングされたウェブデータにRustを接続する準備はできていますか?

reqwestとスクレーパーを型付けされたアプリケーション境界として保持し、Scrapelessがレンダリングが必要なページの取得を処理します。

今すぐサインアップして $5の無料クレジットを獲得クレジットカード不要.

$5のクレジットを請求→

FAQ

ウェブスクレイピングに使用されるRustクレートはどれですか?

reqwestは一般的なHTTPクライアントで、スクレーパーはHTML解析とCSSセレクタを提供し、Tokioは非同期作業を実行します。Serdeは出力または取得応答がJSONの場合にしばしば追加されます。

reqwestはJavaScriptを実行できますか?

いいえ。reqwestはHTTPリクエストを送信し、サーバーの応答を返しますが、ブラウザのイベントループを実行しません。スクリプトが必要なコンテンツを作成するときは、レンダリングされた取得を使用します。

小さなスクレイパーにasync Rustは必要ですか?

いいえ。ブロックするクライアントは単一の逐次ジョブに適している場合があります。async Rustは、設計に複数の独立したネットワークの待機および明確な同時実行予算があるときに便利になります。

Rustは欠Missingスクレイピングフィールドをどのように処理すべきですか?

Rustは必須のフィールドを存在しなければならない値としてモデル化し、オプショナルフィールドを Optionアイデンティティフィールドが欠落しているレコードを拒否し、あいまいなブランクで代替するのではなく。

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

言語は法的分析を変えません。作業は承認された公共データに制限し、サイトの利用規約とロボットの指示を確認し、アクセス制御を尊重し、人々や規制されたデータに影響を与える収集がある場合は法的助言を得てください。

参考文献