Loading Light/Dark Toggle
Playwright を使って無限スクロール商品コレクションをクロールする

Playwright を使って無限スクロール商品コレクションをクロールする方法

Scrapeless Agent Browser は Playwright 駆動のクラウドセッションを実行し、Scrapeless Residential Proxies は、適格なコレクションジョブ向けにロケーション指定された経路を提供します。

要約

  • コレクションの進捗は商品の識別子の集合です。 仮想化されたグリッドは、DOM ノード数を増やさずにカードを入れ替えることができます。
  • 各スクロール操作には観測可能な結果が必要です。 固定の待機時間を数える代わりに、カーソル、バッチマーカー、または次に期待されるアイテムを監視します。
  • クロールには完了理由が必要です。 明示的な終了シグナルと、進捗がない状態および設定された作業上限とを区別します。
  • 商品発見と価格収集には別々の契約があります。 一覧カードは URL を特定し、詳細ページはバリアント固有のオファーを確認できます。

次のコレクションページを読み込む要因を特定する

無限スクロールの商品コレクションは、ユーザーがトリガーに到達したときに追加の商品を要求します。このトリガーはページ端、セントネル要素、あるいは入れ子になったコンテナの下端かもしれません。 Intersection Observer specification は、ページがどのようにビューポートまたはコンテナ境界を横切るターゲットを監視できるかを説明しています。どの要素が実際にスクロールし、その動作に続いてフェッチが発生するかを特定するには DevTools が役立ちます。フィルター変更後も確認してください。検索、並べ替え、在庫フィルターはそれぞれ別のコレクションを開始することがあります。

まず許可された構造化ソースを探します。ストア所有のフィードやサポートされているページネーションエンドポイントは、カーソル、安定した商品識別子、終了フラグを直接公開している場合があります。コレクションを定義するフィルターは保持します。ユーザー体験そのものが対象である場合は、ブラウザを使って次のバッチがどのように読み込まれ、どの状態がコレクション終了を顧客に伝えているかを確認します。各サーフェスから得たデータは、オーナーと合意した範囲に従って扱ってください。

見かけ上のページ高さは誤解を招くことがあります。仮想化リストは、マウントされた少数のカードを維持し、ユーザーがスクロールするにつれてそれらを再利用します。その高さは最初から予約されている場合があります。その場合、進捗のシグナルは新たに観測されたアイテム ID またはバッチカーソルであり、完了のシグナルはアプリケーションから来ます。最後の可視行の位置は、あくまで手がかりの 1 つに過ぎません。

前提条件とインストール

Playwright と Chromium を備えた Node.js 環境を使用します。小さなプロジェクトに Playwright パッケージを追加し、その Chromium ブラウザをインストールするか設定済みの Chromium 実行ファイルを使用し、まずは自分で制御できるストアフロントのフィクスチャから始めます。実際の統合では、耐久性のあるカード ID と完了シグナルを探してマークアップを確認します。例のテスト ID はフィクスチャ属性です。実店舗向けに関数を適用する際には変更されることが想定されています。

「 Playwright locators 」を使って、商品要素をコレクションにスコープします。広すぎるリンクセレクタは、ナビゲーションや編集カード、レコメンドカルーセルまで拾ってしまうことがあります。カード上の不変な商品 ID か、検証済みの URL パターンを優先してください。証拠として元のリンクを保持し、既知の規則のもとでのみ URL コンポーネントを正規化します。 URL Standard は、ブラウザの URL 解析・直列化の挙動を説明しています。

DOM から離れる前に各バッチを収集する

スクロール位置を動かす前に、現在のカードを安定した ID をキーとするマップに読み込みます。表示されているタイトルと解決済みの商品 URL を ID と一緒に保存します。ユーザーがスクロールバックしたことでカードが再び現れても、そのマップにはその商品の発見行が 1 つ保持されます。複数のバリアントが意図的に別々のカードとして現れる場合は、望ましい発見単位を表すキーを使用します。

次の例は、スクロール可能なパネル、バッチマーカー、連続してマウントされる 2 つの商品カード、そして明示的な終了マーカーを備えた制御されたストアフロントフィクスチャに対して実行されます。権限とページネーションの挙動を確認したうえで、店舗固有のセレクタに同じパターンを適用してください。ライブの Agent Browser セッションには Scrapeless アカウントと、クイックスタートで説明されている接続セットアップが必要です。

async function collect(page, targetUrl, maxRounds = 12) {
  await page.goto(targetUrl, { waitUntil: 'domcontentloaded' });
  const grid = page.getByTestId('collection');
  const cards = grid.locator('[data-product-id]');
  const scroller = page.getByTestId('scroll-pane');
  const seen = new Map();

  for (let round = 0; round < maxRounds; round += 1) {
    await cards.first().waitFor({ state: 'visible' });
    const batch = await cards.evaluateAll(nodes => nodes.map(node => ({
      id: node.getAttribute('data-product-id'),
      title: node.querySelector('a')?.textContent.trim(),
      url: node.querySelector('a')?.href
    })));
    for (const item of batch) {
      if (item.id && item.title && item.url) seen.set(item.id, item);
    }
    if (await page.getByTestId('collection-end').isVisible()) {
      return { status: 'complete', items: [...seen.values()] };
    }
    const batchId = await grid.getAttribute('data-batch');
    if (!batchId) throw new Error('Collection batch identifier is missing');
    await scroller.hover();
    await page.mouse.wheel(0, 240);
    try {
      await page.waitForFunction(previous => {
        const root = document.querySelector('[data-testid="collection"]');
        return root?.getAttribute('data-batch') !== previous;
      }, batchId, { timeout: 3000 });
    } catch (error) {
      if (error.name !== 'TimeoutError') throw error;
      return { status: 'no_progress', items: [...seen.values()] };
    }
  }
  return { status: 'round_limit', items: [...seen.values()] };
}

このフィクスチャは、最初のカードが DOM から削除された後、完了ステータス付きでアイテム ID A と B を返します。例のバッチマーカーはフィクスチャ固有の実装詳細です。自社で運営するストアでは、同じフィルターとカーソルに紐づいた正常なリクエストが、対応するカードがレンダリングされた時点で有用な進捗シグナルとして機能します。遅延した変化は、有界な「進捗なし」結果をもたらすべきです。その結果では、部分的なリストが検査のために利用可能なままになります。

正しいスクロールコンテナを進める

次のアクションは、より多くのカードを読み込む責任を持つ要素をターゲットにしなければなりません。モーダルやカテゴリペインに埋め込まれたコレクションは、window のスクロールを無視する場合があります。例では、ペインにホバーすることで、ホイール入力を正しい領域に載せています。マウントされた行同士が重なりを保つスクロール増分を使用し、ステップ間で ID を取りこぼしていないかを測定します。仮想化グリッドは、ジャンプが大きすぎると中間カードをスキップすることがあります。

ローディングインジケータを観察し、読み込み済みの空コレクションと、一度もカードを生成していないレンダリングとを区別します。意図的な空状態は、商品数 0 の完全な結果になり得ます。スケルトン、アクセスチャレンジ、同意ダイアログ、または壊れたセレクタは、説明的な結果を生成すべきです。それらの経路を扱うようにフィクスチャを拡張してから、空の結果を健全と見なしてください。

「もっと読み込む」ボタンは異なるアクションを必要としますが、同じ進捗モデルを使用します。コレクション内のボタンを選択し、1 回クリックし、その後新しいバッチまたは終了状態を待ちます。完了条件としてグローバルな非活動状態を使うのは避けてください。グリッド外の長時間実行リクエストが残っていても、表示中のコレクションはすでに準備完了になっている場合があります。

フィルター間の完全性を追跡し、変更を保存する

クロールは、そのコレクション構成と観測ウィンドウに対して完了します。要求されたカテゴリ、市場、並び替え、フィルターのパラメータ、最終URL、検出数、完了理由、コレクターのバージョンを保存します。広告された結果数が存在する場合は、比較用に別途記録します。ジョブの実行中にストアフロントが変化することがあるため、不一致は、コレクターの欠陥だけでなく、カタログの変動や重複表示を反映している可能性があります。

ディスカバリーをオファー抽出から独立させておきます。コレクションカードは製品ファミリーを表し、開始価格を表示する場合があります。安定したディスカバリーIDとリンクを、販売者・バリアント・価格・在庫を解決する別の詳細ページワーカーに渡します。 無限スクロールのスクレイピング手順 では、さらに多くのページネーションパターンを扱っており、 地域比較のための価格監視ソリューション は、検出された製品セットが市場に依存する場合に関連します。

既知の想定IDを持つ小さなコレクションでページネーションをテストします。マウントされるノード数がバッチ間で一定に保たれるフィクスチャを追加します。そのうえで、終了マーカーの欠如と停滞したバッチを試験します。返されたステータスとアイテムIDをフィクスチャデータと比較します。同じアダプターがカテゴリとその検索結果をカバーする場合は、フィルター固有のテストを追加します。

必要に応じてブラウザー実行をクラウドに移行する

Playwright コレクターはローカルブラウザー上でも Scrapeless Agent Browser上でも実行できます。 Agent Browser Playwright クイックスタート では、リモートセッション向けにサポートされる接続設定を示しています。各コレクションがレンダリングされたコントロールと一連の入力イベントを必要とする場合は、 動的サイト向け Agent Browser ソリューション を使用してキャパシティ計画を行います。クロール状態と最後に受け入れられたバッチはアプリケーション側で保持します。

地理情報が必要な正当な観測には Residential Proxies を使用し、ストアフロントが実際にどの市場を表示しているかを検証します。固定されたリージョンは、コレクションの並び替えやフィルターを指定するものではありません。それらの設定は別々に保存し、クッキーがカタログに影響し得る場合は各市場での実行を分離しておきます。同じサンプル内で完了ジョブと部分的なジョブを計測した後、 Scrapeless 料金 に対してクラウドブラウザー時間とプロキシトラフィックを見積もります。

クロールが実際に見たものを報告する

明示的な進行マーカーを使用し、安定したアイテムマップを保持します。完了理由を検出されたURLの横に保持し、後続ジョブが完全なコレクションと部分的な結果を区別できるようにします。既知の1つのカテゴリから始め、フィクスチャが仮想化、空のコレクション、停止したローダーをカバーしてからソースを追加します。

動的な商品コレクションを取得する準備はできていますか?

管理されたブラウザーセッションで境界付きの Playwright コレクションを実行します。

今すぐ登録して入手 $5 in free credit — クレジットカード不要.

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

FAQ

無限スクロールのクロールが終了したことはどのように分かりますか?

明示的な終了マーカーまたは検証された終端カーソルがあれば、完全な結果を裏付けられます。上限ラウンド数や新しいバッチの欠如は、その動作が完了としてストア契約で定義されていない限り、部分的な結果です。

カード数が変わらないのに新しい商品が現れるのはなぜですか?

仮想化されたリストは既存要素を再利用し、同じノード数で異なる商品ウィンドウをレンダリングすることがあります。観測した各バッチから安定したIDを収集します。

Playwright コレクションにはプロキシや AI エージェントが必要ですか?

Playwright はコレクションロジックを直接実行します。必要に応じて、市場固有の正当なルーティングのためにプロキシを使用し、結果を受け入れる前にストアフロントの市場を検証します。

アクセス拒否やコレクション制限にはどう対処すべきですか?

拒否されたページではジョブを停止し、そのステータスを記録します。ソース所有者に許可された範囲とレート制限を確認し、必要に応じて適用される利用規約および法律について法務担当と検討します。

ストアがグリッドを再設計した場合、何を変更すべきですか?

新しいレイアウトのフィクスチャに対して、アダプターの安定したIDセレクター、スコープされたコンテナ、完了シグナルを更新します。所有者と合意した同時実行数の範囲内に収め、段階的にスケールします。

商品リンクはフィルター間で重複排除できますか?

安定したIDを使用すれば、同じストアと市場に対するディスカバリー行を重複排除できます。カテゴリ配置や検索順位が重要な場合は、フィルター別の所属レコードを分けて保持します。

参考情報