パーサーの余分なメガバイトは、プロキシプロバイダーへの支払いか、制限に引っかかってIPが禁止されるリスクのいずれかです。WildberriesやOzonから価格を収集したり、数百のプロキシアドレスを通じてAvitoの広告を監視したりする場合、トラフィックの節約はプロジェクトの予算に直接影響します。この記事では、データの完全性と正確性を維持しながら、転送データ量を4〜5倍に削減する具体的な技術的手法を紹介します。
なぜパーサーのトラフィックが予算に影響するのか
ほとんどのプロキシプロバイダーは、レジデンシャルおよびモバイルプロキシを使用量に基づいて課金します。もしあなたのパーサーがWildberriesの商品ページを完全に読み込む場合、画像、推薦スクリプト、分析トラッカー、フォントを含めて、1つのカードあたり2〜3MBを支払うことになりますが、実際には15〜20KBのテキスト(商品名、価格、評価、在庫)が必要です。
1日に50,000〜100,000のカードをスケールアップする場合、「すべてを読み込む」と「必要なものだけを読み込む」の違いは、毎日数十ギガバイトの余分なトラフィックになります。これはプロキシのコストだけでなく、ターゲットサイトへの負荷も増加させ、ボット対策に引っかかるリスクを高め、CAPTCHAやIPの一時的な禁止を受ける可能性が高まります。トラフィックの最適化は、コストの節約とブロックのリスクの低減を同時に実現します。
さらに、1回のリクエストで送信されるデータ量が少ないほど、リクエスト自体の実行が速くなります。これにより、並列性を高め、同じ数のプロキシでより多くのスレッドを起動し、Dolphin AntyやAdsPowerのようなアンチデテクトブラウザがセッションを扱う際に設定する速度制限を超えないようにすることができます。
テクニック1:画像、CSS、フォントのブロック
パーサーがヘッドレスブラウザ(Playwright、Puppeteer、Selenium)を介して動作している場合、トラフィックを2〜3倍に削減する最も簡単な方法は、DOM内のデータに影響を与えない静的リソースの読み込みをブロックすることです。商品画像、ウェブサイトのフォント、動画、CSSスタイルはページの70%の重さを占めますが、テキストや属性の抽出にはまったく関与しません。
from playwright.sync_api import sync_playwright
def block_heavy_resources(route, request):
if request.resource_type in ["image", "media", "font", "stylesheet"]:
route.abort()
else:
route.continue_()
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
page.route("**/*", block_heavy_resources)
page.goto("https://example.com/product/123")
html = page.content()
browser.close()
同様のロジックは、Puppeteerでpage.setRequestInterception(true)を介して、SeleniumではChromeのプロファイル設定でprofile.managed_default_content_settings.images: 2を使用して実装されます。実際には、この設定だけで、視覚コンテンツや広告バナーで過剰に読み込まれたマーケットプレイスのパース時に、50%から70%のトラフィックを削減します。
テクニック2:完全なブラウザの代わりにHTTPリクエストを使用
多くの人が、必要のないところでSeleniumやPlaywrightを使用しています。ページがデータのレンダリングのためにJavaScriptを実行する必要がない場合(これは「ページソースの表示」を開くことで簡単に確認できます)、requestsやhttpxなどのライブラリを介してHTMLを直接取得する方がはるかに有利です。このようなリクエストは、ブラウザのレンダリングエンジン、トラッカーのためのネットワーク呼び出し、二次リソースを伴わないため、キロバイト単位のサイズになります。
import httpx
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
"Accept-Encoding": "gzip, br",
"Accept": "text/html,application/xhtml+xml"
}
proxies = {"http://": "http://user:pass@proxy_host:port",
"https://": "http://user:pass@proxy_host:port"}
with httpx.Client(headers=headers, proxies=proxies, http2=True) as client:
response = client.get("https://example.com/catalog/item/456")
print(len(response.content), "バイト受信")
ブラウザのエミュレーションから直接HTTPリクエストに切り替えることで、サイトがクライアントレンダリングなしで準備されたHTMLを提供する場合、トラフィックは3〜8倍削減されます。唯一の注意点は、これらのリクエストが本物のユーザーと区別しやすくなるため、厳しいアンチボット保護のあるサイトでは、質の高いレジデンシャルプロキシと組み合わせることが重要です。これにより、実際の家庭プロバイダーのIPを提供し、リクエストのブロックの可能性を低減します。
テクニック3:隠れたJSON APIを介したパース
ほとんどの現代のマーケットプレイス(Wildberries、Ozon、Yandex.Marketを含む)は、フロントエンドが呼び出す内部JSON APIを介して商品カードやリストをレンダリングします。これらのエンドポイントは、DevToolsのNetworkタブでXHR/Fetchタイプのリクエストをフィルタリングすることで見つけることができます。通常、このようなリクエストは、商品ID、価格、割引、在庫、評価などのクリーンなデータを含む5〜30KBのJSONを返します。HTMLマークアップやCSSは一切含まれません。
完全なHTMLページとJSON APIへの直接アクセスの間のデータ量の違いは、10〜15倍に達することがあります。追加の利点は、JSONはプログラムでパースしやすいことです:XPathセレクターは不要で、辞書のキーを介して必要なフィールドにアクセスするだけで済みます。欠点は、これらのエンドポイントが特定のヘッダー、セッショントークン、またはリクエスト署名パラメータを必要とすることが多く、これらは事前にメインページやモバイルアプリから抽出する必要があります。
実務者へのアドバイス
隠れたAPIの周りにパーサーを構築する前に、プロキシインターセプター(Charles Proxy、Fiddler)を介してモバイル版のサイトやアプリを確認してください。モバイルAPIは、デスクトップ版のサイトよりもコンパクトで安定したJSONを提供することが多いです。
テクニック4:GzipおよびBrotli圧縮
たとえ完全なHTMLを取得する必要がある場合でも、正しい圧縮を有効にすることで、転送サイズを60〜80%削減できます。多くのカスタムパーサーは、Accept-Encoding: gzip, brヘッダーを送信しないため、サーバーは未圧縮の応答を返します。requestsやhttpxライブラリは、GzipおよびBrotliを自動的に解凍します。重要なのは、リクエストヘッダーで圧縮のサポートを明示的に指定することです。
Brotliは、平均してGzipよりも15〜20%強くテキストHTMLを圧縮しますが、すべてのサーバーがこのアルゴリズムをサポートしているわけではありません。両方のオプションをリクエストし、サーバーに最適なものを選択させるべきです。JSON APIの場合、圧縮の効果はさらに顕著です:辞書の繰り返しキー(「price」、「name」、「rating」)はほぼ完璧に圧縮され、応答のサイズを大幅に削減します。
テクニック5:条件付きリクエストとキャッシュ
同じ商品を1日に何度も監視している場合、チェック間でほとんどのカードは変更されません。If-Modified-Sinceおよび最初のリクエストで取得したETagの値を持つIf-None-Matchヘッダーを使用してください。コンテンツが変更されていない場合、サーバーはほとんどボディなしで304 Not Modifiedステータスを返します — 変更のないページではトラフィックの節約が95%に達します。
import httpx
etag_store = {}
def fetch_with_cache(url, client):
headers = {}
if url in etag_store:
headers["If-None-Match"] = etag_store[url]
resp = client.get(url, headers=headers)
if resp.status_code == 304:
return None # データは変更されていない
etag_store[url] = resp.headers.get("ETag", "")
return resp.content
すべてのサイトがETagを正しくサポートしているわけではありませんが、サポートしているサイトに対しては、このテクニックは定期的な監視時にトラフィックを削減する最も効果的な方法になります — 実際には、変更されたデータに対してのみ支払いを行い、変更のないコンテンツの再読み込みには支払いを行わないのです。
テクニック6:必要なフィールドの選択的パース
時には、サーバー側からの受信トラフィックを削減することができない場合があります — サイトはリクエストに関係なく完全なページを返します。この場合、最適化は処理段階で行われます:もう1つのフィールドを抽出するためにページを再度読み込まないでください。XPathやCSSセレクターを設計して、DOMを1回通過するだけで、価格、名前、品番、在庫、評価などの必要な属性をすべて抽出できるようにしてください。異なるタスクのために異なるパーサーで同じURLに対して再リクエストを行うのではなく。
また、ネストされたページのクロール深度を制限することも有用です。価格監視にカテゴリー(商品リスト)ページのデータで十分な場合は、各商品のカードに個別に移動しないでください — これは重複したトラフィックであり、価格や在庫に影響を与えない説明やレビュー以外の新しい情報を提供しないことがよくあります。
テクニック7:クロールパターンの最適化
URLのデデュプリケーションは基本的ですが、しばしば無視されるテクニックです。マーケットプレイスのカタログは、同じ内容の多数のリンクを生成しますが、異なるソートパラメータ、UTMタグ、またはセッションIDが付いています。キューに入れる前にURLを正規化(トラッキングパラメータの削除、クエリパラメータのソート)することで、大規模なカタログをクロールする際に10〜30%の余分なリクエストを削減できます。
データの変更頻度に基づいてクロールの優先順位を付けることもトラフィックを節約します:需要が高く価格が変動する商品は毎時確認し、希少な商品は1日に1回確認するべきです。このような適応型スケジュールは、すべてのカードを均等にクロールするのではなく、重要なデータの最新性を損なうことなく、リクエストの総数を2〜4倍削減します。
プロキシ戦略との組み合わせ
トラフィックの削減は、プロキシの種類の選択に直接影響します。複雑なアンチボット保護なしで直接HTTPリクエストから大量のページをパースする場合、迅速で安価なデータセンターのプロキシで十分です — これらは、低コストで高い転送速度を提供し、1日に何千ものカードをスケールアップする際に重要です。
ボットに対する厳しい保護があるサイトでは、実際のユーザーの行動を模倣することが重要なため、レジデンシャルプロキシを使用する方が良いです — 不要なリソースをブロックするテクニックと組み合わせることで、低トラフィックと高い信頼性を同時に得ることができます。また、マーケットプレイスのモバイルAPIを介してパースを行う場合、データがコンパクトで、アンチボットシステムがモバイルIPレンジに焦点を当てるため、ブロックのリスクをさらに低減するためにモバイルプロキシを検討する価値があります。
「リクエストあたりの最小トラフィック」と「タスクに応じた正しいプロキシの種類」を組み合わせることで、インフラストラクチャのコストを削減し、信頼性を損なうことなくデータ収集の速度を向上させることができます。
テクニックの比較表
| テクニック | トラフィック削減 | 実装の難易度 |
|---|---|---|
| 画像/CSS/フォントのブロック | 50-70% | 低い |
| ブラウザの代わりにHTTPリクエスト | 3-8倍 | 中程度 |
| 隠れたJSON API | 10-15倍 | 高い |
| Gzip/Brotli圧縮 | 60-80% | 低い |
| 条件付きリクエスト(ETag) | 変更のないページで最大95% | 中程度 |
| URLのデデュプリケーションと優先順位付け | 2-4倍 | 中程度 |
実装チェックリスト
- ターゲットページがJavaScriptレンダリングを必要とするか、
httpx/requestsを介してHTMLを直接取得できるか確認する - ブラウザが必要な場合、ヘッドレスブラウザで画像/メディア/フォント/スタイルシートのブロックを設定する
- DevTools → Network → XHR/Fetchを介して内部JSON APIを見つける
- すべてのリクエストに
Accept-Encoding: gzip, brヘッダーを追加する - 繰り返しURLに対する条件付きリクエストのためにETag/Last-Modifiedを保存する
- クロール前にURLのキューを正規化し、デデュプリケートする
- データの重要性と変動性に基づいて適応型のクロール頻度を設定する
- 最終的なトラフィックプロファイルに基づいてプロキシの種類を選定する — データセンター、レジデンシャル、またはモバイル
結論
パーサーのトラフィックを5倍に削減することは、手法を順番に適用することで現実的な目標です:不要なリソースを削除し、可能な限り直接HTTPリクエストまたはJSON APIに切り替え、圧縮を有効にし、変更のないデータに対して条件付きリクエストを使用し、クロールパターン自体を最適化します。これらの各ステップは測定可能な効果をもたらし、総合的にマーケットプレイスや他のサイトからデータを収集するプロジェクトの経済性を根本的に変えます。
トラフィックの最適化後は、新しい負荷プロファイルに合わせてプロキシインフラストラクチャを適切に選定することが重要です。大量のデータを迅速かつ安価に収集するには、データセンターのプロキシが適しており、厳しいアンチボット保護のあるサイトで作業する場合は、実際の家庭プロバイダーのIPアドレスを持つレジデンシャルプロキシを使用することで、集中的なパーシングでもブロックのリスクを低減します。