スクレイピング用のローテーティングプロキシ: 設定と落とし穴
ローテーティングプロキシは、トラフィックが出ていく IP アドレスを、リクエストごとか、設定した間隔ごとに変更します。ウェブスクレイピングで最もよく使われるツールの一つであり、最も誤用されるものの一つでもあります。ローテーションが少なすぎると、一つのアドレスがレート制限されます。多すぎると、トラフィックは訪問者のものにまったく見えなくなります。このガイドでは、二つのローテーションのモデルを説明し、停止したプロキシに対するリトライを備えた動作する Python の構成を示し、プロキシのフィールドがキャプチャ解決にどのように組み込まれるかを扱います。
ローテーションとスティッキーセッション
ローテーティングプロキシのサービスがアドレスを割り当てる方法は二つあります。
- リクエストごとのローテーション。 すべてのリクエストが新しい出口アドレスを得ます。互いに関係のない多数のページを大量にクロールする場合に適しています。前のページに依存するページがないためです。
- スティッキーセッション。 一つのアドレスが、数分などの設定時間、またはあなたが解放するまで維持されます。ログイン、ショッピングカート、クッキーが重要なページ送りのリストなど、状態を必要とする作業に適しています。
実際の訪問者は、一回の訪問の間ずっと一つのアドレスを保ちます。スティッキーセッションはその振る舞いを再現するため、サイトがクッキーやセッションを使う場合は、通常より良い初期設定になります。ステートレスなクロールには、リクエストごとのローテーションを使ってください。
Python での基本的なローテーションプール
以下の例では、プロキシ URL のプールを保持し、順番に切り替え、一つが失敗したら次に進みます。認証情報は環境変数に保持し、ソースコードには書かないでください。
import itertools
import os
import requests
# プロキシ URL は環境変数から取得します。例:
# PROXY_POOL="http://user:pass@203.0.113.10:8080,http://user:pass@203.0.113.11:8080"
PROXIES = [p.strip() for p in os.environ.get("PROXY_POOL", "").split(",") if p.strip()]
rotation = itertools.cycle(PROXIES)
def fetch(url: str, max_tries: int = 3) -> requests.Response:
last_error = None
for _ in range(max_tries):
proxy = next(rotation)
try:
r = requests.get(
url,
proxies={"http": proxy, "https": proxy},
timeout=30,
)
if r.status_code == 407: # プロキシの認証に失敗
raise requests.RequestException("proxy auth rejected")
return r
except requests.RequestException as exc:
last_error = exc # 停止または低速なプロキシ: 次のものを試す
raise RuntimeError(f"all attempts failed for {url}: {last_error}")
ここで重要な点は二つあります。第一に、停止したプロキシは、同じアドレスではなく別のアドレスでリトライすべきです。第二に、認証エラーで失敗したリクエストは、プール全体を使い切るのではなく、停止して報告すべきです。
プロキシの状態を追跡する
単純なラウンドロビンでは、失敗し始めたプロキシにもトラフィックを送り続けてしまいます。各アドレスについて簡単なスコアを記録し、最近の失敗数を数えてください。しきい値を超えたら、クールダウン期間の間プールから外し、後で戻して再び監視します。こうすると、スクレイパーはプールの健全な部分にリクエストを使うようになります。
各結果に使用したプロキシを記録してください。サイトがブロックを返し始めたとき、一つのアドレス、一つの地域、あるいはプール全体のどれが原因かを知りたくなります。
プールのペースを守る
ローテーションはアドレス全体に負荷を分散しますが、各アドレスにはやはりレートがあります。アドレスごとの遅延と、プール全体での1秒あたりのリクエスト数の上限を設定してください。ローテーションは、より多くのトラフィックを送る許可ではありません。一つのアドレスからのトラフィックを妥当な範囲に収めるための手段です。
よくある間違い
ローテーションに関する問題の多くは、いくつかの習慣から生じます。ログインや決済の途中でアドレスを変えると、セッションが壊れ、サイトに不審に思われます。429 の応答はサイトのレート制限であり、壊れたプロキシではありません。そのため、新しいアドレスに切り替えてすぐにリトライしても、問題を広げるだけです。同じクッキーを保ったままリクエストごとにアドレスを変えることも一貫性がありません。クッキーは別の訪問者に発行されたものだからです。最後に、一度も確認されないプールは、静かに停止したアドレスで埋まり、原因がはっきりしないままエラー率が上がっていきます。プールをスケジュールに沿って確認し、失敗したものは取り除いてください。
プロキシとキャプチャ解決
一部のキャプチャのタスクは、スクレイパーが使うプロキシを利用できます。オプションの proxy フィールドに http://user:pass@host:port の形式で渡すと、解決はページのリクエストと同じネットワーク経路から行われます。プロキシなしのタスクでは、このフィールドを完全に省きます。どちらを選ぶかは、サイトがキャプチャをネットワークアドレスに結びつけているかどうかによります。そのトレードオフはプロキシありとなしのキャプチャ解決で説明しています。
実務上の要点は二つです。
- サイトがアドレスを確認する場合は、ページのリクエストとキャプチャ解決に同じプロキシを使ってください。アドレスを混ぜると、トークンが失敗することがあります。
- トークンの有効期限は短いです。フォームを送信する直前にトークンを取得し、かなり前に取得しておかないでください。キャプチャトークンの有効期限を参照してください。
Scarnox で現在ライブのキャプチャ種別は PopularCaptcha です。リクエストの仕方と、返されたトークンの送信方法は、PopularCaptcha の Python ガイドで示しています。
プロキシの選び方
ローテーションするアドレスの種類は、ローテーションそのものと同じくらい重要です。データセンターのアドレスは、リクエストあたりの速度が速く、安価ですが、スコアが低くなりがちです。住宅用のアドレスはスコアが良く、遅いです。住宅用とデータセンタープロキシの比較で詳しく比較しており、そこでの助言はここで作るプールにも当てはまります。
責任を持ったスクレイピング
- スクレイピングするサイトの robots.txt と利用規約を読んでください。
- プロキシは正当な負荷を分散するために使い、所有者が設けた制限を回避するために使わないでください。
- 同意に基づいて住所が調達されているプロキシサービスのみを使ってください。同意していない人が所有するデバイスを経由させるのは許容されません。
- 認証情報はコードやログに残さないでください。
次のステップ
無料トライアルクレジットから始められ、クレジットカードは不要です。アカウントを作成して、自分のプロキシを使った PopularCaptcha のフローをテストしてください。現在の料金は料金ページをご覧ください。