اگر در پایتون چیزی را در مقیاس بزرگ اسکرپ، کرال یا خودکارسازی میکنید، دیر یا زود سایت هدف متوجه میشود که همهٔ درخواستها از یک IP میآیند و شما را مسدود میکند. چرخش پروکسی در پایتون ترافیک شما را روی دهها آدرس IP پخش میکند تا هیچ IPای بهتنهایی به محدودیت نرخ نخورد یا بن نشود. این راهنما کد دقیق را برای requests، httpx و aiohttp نشان میدهد و توضیح میدهد چطور بین یک gateway چرخشی و یک استخر IP مدیریتشده انتخاب کنید.
دو تصمیم کلیدی همهٔ چیزهای پایین را شکل میدهند. اول: سشن چرخشی در برابر sticky — یک IP تازه برای هر درخواست، یا یک IP ثابت برای یک جریان چندمرحلهای. دوم: IP مسکونی در برابر دیتاسنتر — به ماتریس تصمیم نوع پروکسی نگاه کنید. این دو را درست انتخاب کنید، نوشتن کد بخش آسان ماجراست.
۱. چرخش از طریق gateway (توصیهشده). شما به یک endpoint واحد وصل میشوید و ارائهدهنده در هر اتصال جدید یک IP خروجی تازه به شما میدهد. نه فهرستی برای مدیریت، نه IP مردهای برای حذف. استخر مسکونی پویای JIBAO اینگونه کار میکند: همان host و port، یک IP جدید در هر درخواست.
۲. فهرست IP خودمدیریتی. شما فهرستی از ورودیهای host:port نگه میدارید و در هر درخواست یکی را انتخاب میکنید. کنترل بیشتر، اما خودتان مسئول سلامتسنجی، retry و ردیابی بن هستید. وقتی به آدرسهای شناختهشده و پایدار نیاز دارید با IP اختصاصی دیتاسنتر مفید است.
سادهترین حالت — هدایت یک درخواست از طریق gatewayای که برای شما میچرخد. از socks5h:// استفاده کنید (آن h انتهایی یعنی DNS در سمت پروکسی resolve میشود، که از نشت lookup جلوگیری میکند):
import requests
# gateway مسکونی چرخشی JIBAO: یک IP خروجی تازه در هر اتصال
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"]) # در هر حلقه یک IP متفاوت
میخواهید requests با SOCKS5 کار کند؟ افزونه را نصب کنید: pip install "requests[socks]". اگر endpoint پروکسی HTTP را ترجیح میدهید، scheme را به 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") # همان IP، سشن دستنخورده
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"])
پشتیبانی SOCKS در httpx نیازمند pip install "httpx[socks]" است. برای HTTP/2 آرگومان http2=True را به کلاینت اضافه کنید — این کار ترافیک شما را شبیهتر به یک مرورگر واقعی میکند، که خوب با تطبیق fingerprint از نوع TLS جفت میشود.
برای throughput بالا، چندین درخواست را یکجا شلیک کنید. هر اتصال از طریق gateway 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 تازه دوباره امتحان کنید. بهصورت نمایی backoff کنید و در هر تلاش توکن سشن را بچرخانید:
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 واقعاً عوض میشود. چند بار یک endpoint بازتابدهنده را بزنید و ببینید که IPها متفاوتاند. برای اینکه مطمئن شوید fingerprint از نوع TLS شما را لو نمیدهد، درخواست را روی بررسیکنندهٔ رایگان fingerprint از نوع JA3/TLS اجرا کنید — یک IP چرخشی با fingerprint پایتونی لورفته باز هم مسدود میشود.
وقتی چرخش محکم شد، دیوار بعدی که به آن میخورید معمولاً fingerprinting است، نه IP. اگر IPهای مسکونی تمیز باز هم 403 میگیرند، روش دور زدن fingerprint از نوع TLS با curl_cffi و دستورالعمل کامل دور زدن Cloudflare را بخوانید.
۵ دلار اعتبار رایگان و یک gateway مسکونی چرخشی که در هر درخواست یک IP جدید به شما میدهد.
شروع تست رایگانکاربران جدید با ثبتنام 500MB هدیه میگیرند، بهعلاوه بونوس اولین شارژ. پیشنهاد محدود.