Python で大規模にスクレイピング、クロール、または自動化を行うと、遅かれ早かれ、ターゲットサイトはすべてのリクエストが 1 つの IP から来ていることに気づき、あなたを締め出します。Python でのプロキシローテーションは、トラフィックを多数の IP アドレスに分散させ、どの 1 つの IP もレート制限に引っかかったり BAN を食らったりしないようにします。本ガイドでは、requests、httpx、aiohttp の正確なコードと、ローテーションゲートウェイとマネージド IP プールのどちらを選ぶべきかを示します。
以下のすべてを左右する横断的な判断が 2 つあります。1 つ目:ローテーション vs スティッキーセッション — 1 リクエストごとに新しい IP にするか、複数ステップのフローのために 1 つの IP を保持するか。2 つ目:residential vs datacenter IP — プロキシタイプの判断マトリクスを参照してください。この 2 つを正しく押さえれば、コードは簡単な部分です。
1. ゲートウェイローテーション(推奨)。 単一のエンドポイントに接続すると、新しい接続ごとにプロバイダーが新鮮な出口 IP を渡してくれます。管理すべきリストもなく、削除すべき死んだ IP もありません。JIBAO のダイナミック residential プールはこの方式で動作します:同じホストとポートで、リクエストごとに新しい IP です。
2. 自己管理の IP リスト。 host:port エントリのリストを保持し、リクエストごとに 1 つを選びます。コントロールは増えますが、ヘルスチェック、リトライ、BAN 追跡を自分で担うことになります。既知の安定したアドレスが必要なときに専用 datacenter IP と組み合わせて役立ちます。
最もシンプルなケース — あなたの代わりにローテーションしてくれるゲートウェイ経由で 1 つのリクエストをルーティングします。socks5h:// を使ってください(末尾の h は DNS がプロキシ側で解決されることを意味し、名前解決の漏洩を防ぎます):
import requests
# JIBAO rotating residential gateway: a new exit IP per connection
PROXY = "socks5h://USERNAME:[email protected]:10001"
proxies = {"http": PROXY, "https": PROXY}
for _ in range(5):
r = requests.get("https://httpbin.org/ip", proxies=proxies, timeout=30)
print(r.json()["origin"]) # a different IP each loop
requests に SOCKS5 を話させる必要がありますか?エクストラをインストールしてください:pip install "requests[socks]"。HTTP プロキシエンドポイントを好む場合は、スキームを http:// に切り替えてください — 残りは同一です。
import random
import requests
PROXY_POOL = [
"socks5h://USERNAME-country-us:[email protected]:10001",
"socks5h://USERNAME-country-uk:[email protected]:10001",
"socks5h://USERNAME-country-de:[email protected]:10001",
]
def fetch(url):
proxy = random.choice(PROXY_POOL)
return requests.get(url, proxies={"http": proxy, "https": proxy}, timeout=30)
resp = fetch("https://example.com")
print(resp.status_code)
ログインフロー、カート、ページネーション結果は、タスクの途中で IP が変わると壊れます。ユーザー名にセッショントークンを追加して IP を固定し、同じトークンを再利用することで、その寿命の間は同じ出口 IP を保ちます:
import requests
SESSION_ID = "task-0001"
PROXY = f"socks5h://USERNAME-session-{SESSION_ID}:[email protected]:10001"
s = requests.Session()
s.proxies = {"http": PROXY, "https": PROXY}
s.post("https://example.com/login", data={"u": "me", "p": "secret"})
s.get("https://example.com/dashboard") # same IP, session intact
httpx は HTTP/2 とネイティブ async を備えたモダンなクライアントを提供します。新しいバージョンでは単一の proxy= 引数を取ることに注意してください:
import httpx
PROXY = "socks5h://USERNAME:[email protected]:10001"
with httpx.Client(proxy=PROXY, timeout=30) as client:
for _ in range(5):
print(client.get("https://httpbin.org/ip").json()["origin"])
httpx での SOCKS サポートには pip install "httpx[socks]" が必要です。HTTP/2 を使うには、クライアントに http2=True を追加してください — これによりトラフィックが本物のブラウザにより近く見えるようになり、TLS フィンガープリントの一致とよく組み合わさります。
高スループットには、多数のリクエストを一度に発射します。ゲートウェイを通る各接続が独自の出口 IP を得るため、並行性とローテーションが同時に実現します:
import asyncio
import aiohttp
from aiohttp_socks import ProxyConnector
PROXY = "socks5://USERNAME:[email protected]:10001"
async def fetch(url):
connector = ProxyConnector.from_url(PROXY)
async with aiohttp.ClientSession(connector=connector) as session:
async with session.get(url, timeout=aiohttp.ClientTimeout(total=30)) as r:
return await r.text()
async def main():
urls = ["https://httpbin.org/ip"] * 20
results = await asyncio.gather(*(fetch(u) for u in urls))
print(f"fetched {len(results)} pages")
asyncio.run(main())
SOCKS コネクタは pip install aiohttp_socks でインストールします。各リクエストが新しいプロキシ接続を開くように、タスクごとに新鮮なコネクタを作ってください。
ローテーションは、失敗を新鮮な IP でリトライしてこそ報われます。指数的にバックオフし、試行ごとにセッショントークンをローテーションしてください:
import requests
from time import sleep
def fetch_with_retry(url, max_retries=4):
for attempt in range(max_retries):
proxy = f"socks5h://USERNAME-session-r{attempt}:[email protected]:10001"
try:
r = requests.get(url, proxies={"http": proxy, "https": proxy}, timeout=30)
if r.status_code in (403, 429):
raise requests.HTTPError(f"blocked: {r.status_code}")
r.raise_for_status()
return r.text
except requests.RequestException:
sleep(2 ** attempt) # 1s, 2s, 4s, 8s
raise RuntimeError(f"failed after {max_retries} tries: {url}")
大きな実行の前に、IP が実際に変わっていることを確認してください。echo エンドポイントを数回叩いて、IP が異なることをチェックします。TLS フィンガープリントが正体を暴いていないことも確認するには、JIBAO の無料の JA3/TLS フィンガープリントチェッカーに対してリクエストを実行してください — ローテーションする IP でも、Python のフィンガープリントが丸わかりであれば依然としてブロックされます。
ローテーションが盤石になると、次にぶつかる壁はたいてい IP ではなくフィンガープリントです。クリーンな residential IP でも依然として 403 が返るなら、curl_cffi で TLS フィンガープリントを回避する方法と、完全な Cloudflare 回避レシピを読んでください。
500MB の無料トラフィックと、リクエストごとに新しい IP を渡すローテーション residential ゲートウェイを手に入れましょう。
無料トライアルを始める新規ユーザーは登録時に500MBを獲得、さらに初回チャージにボーナスが付きます。期間限定オファーです。