「すべてのリクエストでローテーションすべきか?」は、チームがレジデンシャルプロキシを使い始めたときに最初に浮かぶ疑問の一つであり、正直な答えは「リクエスト同士に何の共通点があるか次第」です。ローテーションしすぎると、サイトが単一の訪問者から来ると想定しているフローが壊れます。ローテーションが少なすぎると、すべてのトラフィックが一つのアドレスに集中します。どちらもブロック、再試行、帯域の無駄につながります。
このガイドでは、判断のためのシンプルな方法を示します。判断すべき問いはプロキシについてのものではありません。あなたの作業についての問いです。どのリクエストが一つのまとまりとして扱われるべきか、そしてそれはどのくらいの時間続くのか、という点です。
3つのモード
| モード | 動作 | Shifterでの実装 |
|---|---|---|
| リクエストごとにローテーション | リクエストごとに異なるレジデンシャルIPから送信される | デフォルト: ユーザー名にセッションフラグなし |
| スティッキーセッション | 同じセッションIDを持つリクエストは、セッションが終了するまで一つのIPを共有する | ユーザー名にsid-<id>を追加、任意でttl-<seconds>も追加。デフォルトの有効期間は120秒 |
| 固定IP | 選択した都市とISPの一つのアドレスを請求期間全体で使用 | ISPプロキシ |
スティッキーセッションは、その背後にあるレジデンシャルIPが切断された場合にも早期に終了するため、セッションを使用するコードは、セッション途中で新しいIPに切り替わることがあると想定しておくべきです。スティッキーセッションはリージョンごとに保持されるため、一つのセッションを共有するツールは同じリージョンのエントリーポイントを通じて接続する必要があります。
判断すべき問い: 何がひとまとまりなのか
スクレイパーが繰り返す最小の作業単位を見極め、それについて2つのことを問いましょう。
1. 一つのまとまりはいくつのリクエストで構成されるか? 単独で取得する商品ページは1つのリクエストです。検索とそれに続く6つの詳細ページはフローです。チェックアウトのテストは、カート、セッションクッキー、場合によってはCSRFトークンといった状態を持つフローです。
2. 一つのまとまりにどれくらいの時間がかかるか? 秒単位か、分単位か、時間単位か。
この2つの答えから:
- 独立した単一のリクエスト: ローテーションする。 各ページは単独で完結するため、IPを維持するメリットはなく、多数のアドレスにリクエストを分散させることで、どれか一つが「稼働しすぎ」に見えるのを防げます。
- 30分以内に終わるフロー: スティッキーセッション。 サイトは最初のリクエストでクッキーを設定し、残りのフローも同じ訪問者から来ることを期待します。検索やカートの途中でIPが変わると、セッションが乗っ取られたように見え、これは突然のブロックや状態の喪失のよくある原因です。
- それより長いもの、または何度も戻ってくるログイン: 固定IP。 スティッキーセッションは時間単位ではなく、分単位のために作られています。一日中続くセッションや、毎日使うアカウントには、ISPプロキシを使いましょう。詳細は長時間セッション向けのISPプロキシ設定のガイドで解説しています。
コードで表すと
以下の2つの関数は、このルールをコード化し、対応するShifterのユーザー名を構築します。
def proxy_username(user, country=None, session_id=None, ttl_seconds=None):
"""Build a Shifter residential username: rotate per request, or stick to one IP."""
parts = [f"customer-{user}"]
if country:
parts.append(f"country-{country}")
if session_id:
parts.append(f"sid-{session_id}")
if ttl_seconds:
parts.append(f"ttl-{ttl_seconds}")
elif ttl_seconds:
raise ValueError("ttl only works together with a session id")
return "-".join(parts)
def choose_rotation(steps, minutes, needs_login=False, same_ip_required=False):
"""Pick a rotation mode for one unit of work.
steps: requests that belong together (one page = 1, a checkout flow = many)
minutes: how long that unit of work takes
"""
if needs_login and minutes > 30:
return "isp" # a login that outlives a sticky session
if steps == 1 and not same_ip_required:
return "rotate" # independent requests: new IP each time
if minutes <= 30:
return "sticky" # a short flow: one IP until it ends
return "isp"
4つの典型的なジョブに適用すると次のようになります。
from rotation import choose_rotation, proxy_username
jobs = { # session ids must not contain hyphens: the username uses them as separators
"products": dict(steps=1, minutes=0.1),
"search": dict(steps=6, minutes=2),
"checkout": dict(steps=15, minutes=8),
"seller": dict(steps=400, minutes=240, needs_login=True),
}
for name, job in jobs.items():
mode = choose_rotation(**job)
if mode == "rotate":
user = proxy_username("USERNAME", "us")
elif mode == "sticky":
user = proxy_username("USERNAME", "us", session_id=name, ttl_seconds=job["minutes"] * 60 + 120)
else:
user = "an ISP proxy username from your plan"
print(f"{name:<9} {mode:<7} {user}")
products rotate customer-USERNAME-country-us
search sticky customer-USERNAME-country-us-sid-search-ttl-240
checkout sticky customer-USERNAME-country-us-sid-checkout-ttl-600
seller isp an ISP proxy username from your plan
TTLは、フローの想定時間に2分の余裕を加えた値に設定されるため、セッションは作業が終わるまで保持されつつ、不必要に長く残ることもありません。同時に実行する各フローには、それぞれ固有のセッションIDを与えてください。2つのワーカーが一つのIDを共有すると、一つのIPを共有することになり、本来の目的が損なわれます。
選択がコストと成功率に与える影響
成功率。 最もよくあるローテーションの誤りは、フローの途中でローテーションしてしまうことです。最初のリクエストでクッキーを取得し、2番目のリクエストが別の国のISPから、そのクッキーを持った状態で届くと、サイトはそれを不審とみなします。フローに対するスティッキーセッションは、他のどの単一の変更よりも多くの失敗を修正することが通常です。逆に、何千もの独立したリクエストを一つのスティッキーIPで送信すると、そのアドレスはボットのように見えてしまいます。両方の失敗パターンについては、スティッキーレジデンシャルプロキシとローテーティングプロキシの比較のガイドで詳しく解説しています。
帯域。 レジデンシャルトラフィックはギガバイト単位で課金され、ローテーション自体がそれを変えることはありません。変化をもたらすのは再試行です。失敗したフローはすべて再度ダウンロードされます。作業内容にモードを合わせることで再試行が減り、そこから節約が生まれます。スティッキーセッション内では、同じ接続とクッキーを再利用することで、同じアセットの二重ダウンロードも回避できます。
速度。 リクエストごとのローテーションは、リクエストごとに新しい経路を意味します。さらに毎回新しい接続を開く場合、セットアップ時間が積み重なります。ローテーションのモードよりも、接続の再利用の方が重要です。スクレイパーが遅いのは、おそらくプロキシのせいではないというテストで、その影響を測定しています。
選択を誤ったときの兆候
| 見られる現象 | 考えられる原因 | 対処法 |
|---|---|---|
| 最初のステップの後にフローが失敗する。カートやセッションが失われる | フロー内でローテーションしている | フローごとにスティッキーセッションを使う |
| バースト的なリクエストの後に一つのIPがブロックされる | 一つのスティッキーセッションに独立した作業が多すぎる | 独立したページにはリクエストごとのローテーションを使う |
| 作業完了前にセッションが切れる | TTLが短すぎる、またはフローがスティッキーセッションには長すぎる | TTLを上げる。時間単位の作業はISPプロキシへ移す |
| 2つのワーカーが互いに干渉する | セッションIDの共有 | 同時実行フローごとに一つのセッションID |
| ログインが毎日チャレンジを受ける | ローテーティングIPまたはスティッキーIPでのログイン | アカウントごとに固定のISP IP |
FAQ
すべてのリクエストでプロキシIPをローテーションすべきですか?
関連のない商品ページの取得のような、独立したリクエストの場合はそうです。検索、カート、ログインのような、状態を共有する複数のリクエストにまたがる場合は、フロー全体を通して一つのIPをスティッキーセッションで維持してください。
スティッキーセッションはどのくらいの長さにすべきですか?
それが処理するフローと同じ長さに、わずかな余裕を加えた長さです。Shifterではデフォルトは120秒で、ttl-<seconds>で設定できます。約30分を超えるフローや、何度も戻ってくるログインは、ISPプロキシに適しています。
IPのローテーションはブロックを減らしますか?
負荷を分散させることで、どのアドレスも「稼働しすぎ」に見えなくなるため、独立したリクエストには効果があります。フロー内でのローテーションは逆効果で、一人の訪問者が多数の訪問者のように見えてしまい、サイトにブロックされやすくなります。
ローテーションは帯域コストに影響しますか?
レジデンシャルトラフィックは量で課金されるため、直接的には影響しません。間接的には、誤ったモードを選ぶとフローが失敗し、再試行によって再ダウンロードが発生し、請求額が増えます。
結論
独立した作業にはリクエストごとにローテーションし、ひとまとまりのフローにはそれぞれスティッキーセッションを維持し、時間単位で続く作業や何度も戻るログインには固定のISP IPを使いましょう。プロキシの設定ではなく、作業単位を見て判断し、同時実行する各フローには固有のセッションIDを与え、上記の表にある兆候に注意してください。各モードの仕組みについては、レジデンシャルプロキシのローテーションの仕組みの解説記事で詳しく説明しています。