2026年版 Webスクレイピングのベストプラクティス:実践者のガイド
3,100人を超えるユーザーに成功率99%超でサービスを提供する、15のプロダクションスクレイパーを構築・保守してきた経験から、本当に重要なプラクティスをまとめました。
アーキテクチャ:スクリプトではなくパイプラインとして考える
よくある最大の過ちは、スクレイピングを単一ステップの処理として扱ってしまうことです。プロダクションスクレイパーはデータパイプラインです。
- URL探索 — 何をスクレイピングするかを見つける(サイトマップ、カテゴリページ、検索、API)
- リクエスト実行 — 適切なリトライとローテーションでデータを取得する
- パース — 生のレスポンスから構造化フィールドを抽出する
- 正規化 — 出力をクリーンアップ・検証・標準化する
- 保存 — データセット、データベース、または下流システムへ送信する
各ステップは独立してテスト・リトライ可能であるべきです。Sephoraが商品ページのレイアウトを変更しても、更新が必要なのはステップ3だけで、パイプラインの残りは安定したままです。
HTML解析よりも常にAPIを優先する
CSSセレクタを1つでも書く前に、対象サイトに以下があるか確認しましょう。
- 公開API — JSONを返す、ドキュメント化されたエンドポイント
- プライベートAPI — ブラウザのDevToolsで確認できるXHR/fetch呼び出し
- GraphQLエンドポイント — 近年増加傾向にあり、多くの場合introspectionが有効
- 埋め込みJSON — HTML内の
__NEXT_DATA__、window.__INITIAL_STATE__、またはJSON-LD
APIレスポンスは構造化されておりバージョン管理もされているため、HTMLレイアウトよりもはるかに安定しています。私のSephoraスクレイパーはすべてのWeb URLをAPI呼び出しに変換しており、フロントエンドの刷新で壊れたことは一度もありません。
プロキシ戦略:防御レベルに合わせる
すべてのサイトにレジデンシャルプロキシが必要なわけではありません。私が使っている判断基準は以下の通りです。
| 防御レベル | プロキシタイプ | 対象サイト例 |
|---|---|---|
| なし/Basic | データセンター | 大半のShopifyストア、小規模サイト |
| レート制限 | ローテーション型データセンター | 中規模EC、コンテンツサイト |
| フィンガープリンティング | レジデンシャル | Sephora、Farfetch、大手ブランド |
| 高度なWAF | レジデンシャル+TLSフィンガープリント | Akamai、Cloudflare Enterprise |
重要な洞察: プロキシコストは防御レベルに比例します。IPレピュテーションしかチェックしないサイトに、レジデンシャルプロキシで無駄なコストをかけないでください。私のShopifyスクレイパーはデータセンタープロキシで問題なく動作します。Shopifyのデフォルトの防御は最小限だからです。
セッション管理がすべて
成功率60%と99%の違いは、たいていセッション管理にあります。
- IPだけでなくセッションもローテーションする — 同じCookieのまま新しいIPを使うと不審に見えます
- セッションをウォームアップする — 商品ページにアクセスする前にホームページを訪問する
- レート制限を守る — ブロックされる50並列より、通る5並列の方が優れています
- 指数バックオフ — 即座のリトライではなく、1秒・2秒・4秒・8秒間隔でリトライする
私のSephora EUスクレイパーは、自動リフレッシュと指数バックオフでゲストトークンを管理します。実際の閲覧パターンに見える永続的なセッションを維持します。
出力を正規化する
スクレイピングした生データは乱雑です。すべてを正規化しましょう。
価格
ドルではなく整数(セント単位)で保存します。$29.99は2999になります。これにより、下流の金融データを破損させる浮動小数点の精度誤差を回避できます。私のすべてのECスクレイパーがこの規約を採用しています。
URL
相対パスではなく、常に絶対URLを保存してください。抽出時点で解決しておきます。
日付
ISO 8601形式(2026-04-01T00:00:00Z)を使い、常にタイムゾーンを含めます。ロケール依存の日付フォーマットで保存してはいけません。
テキスト
余分な空白を除去し、Unicodeを正規化し、HTMLの扱い方針(タグを除去するか、書式を保持するか)を決めておきます。
エラーハンドリング:失敗は前提
プロダクションスクレイパーは常に失敗します——問題は、いかに優雅に失敗するかです。私のアプローチは以下の通りです。
1Request fails (network error, timeout, 4xx/5xx)
2 → Retry with exponential backoff (up to 5 attempts)
3 → Rotate session/proxy on retry
4 → Log failure with full context if all retries exhausted
5 → Continue processing remaining URLs (don't crash the batch)
URLパターンごとに成功率を追跡しましょう。/category/*ページの成功率が突然90%を下回ったら、サイト側で何かが変更された可能性が高いです——ユーザーから報告される前に気づけます。
監視とアラート
監視のないスクレイパーは、静かに壊れるのを待っているだけです。以下を追跡しましょう。
- 成功率 — 実行ごと、URLパターンごと
- 出力件数 — 急激な減少は、何かが壊れたサインです
- データ品質 — nullフィールド、想定外の値、スキーマ違反
- コスト — プロキシ使用量、計算時間、ストレージ
私のApifyアクターはすべて、これらのメトリクスを公開しています。成功率が落ち込むと数時間以内に通知が届きます——多くの場合、ユーザーが気づくより先にです。
シンプルに始め、複雑さは後から加える
私が構築するスクレイパーはすべて、動作する最もシンプルな形から始まります。
- まずHTTP+Cheerio(最速・最安)
- ブロックされた場合のみフィンガープリンティングを追加
- JavaScriptが必要な場合のみブラウザレンダリングを追加
- レート制限にかかった場合のみプロキシローテーションを追加
私のUltaスクレイパーは純粋なCheerioのみで、ブラウザは不要です。私のUniversal Web PrinterはJavaScriptのレンダリングが必須のためPlaywrightを使用しています。適材適所です。
これらは机上の理論ではなく、数百万件のリクエストを処理する実際のプロダクションスクレイパーの運用から導き出されたものです。こうしたプラクティスに基づくカスタムスクレイパーが必要な方は、お気軽にご相談ください。