مقدمه
در این مقاله بهصورت عملی میآموزیم چگونه پروکسیها را در اسکریپینگ با Python Requests بهکار ببریم، احراز هویت پروکسی و نحوهٔ چرخش پروکسیها را پیادهسازی کنیم و تفاوت بین فرمتهای رایج پروکسی را بررسی میکنیم. هدف این است که پس از خواندن، بتوانید پروکسی را در پروژهٔ واقعی اضافه کنید، روتینهای خطا و retry را پیادهسازی کنید و برای مقیاسپذیری پروکسیها را مدیریت کنید.
افزودن پروکسی ساده به requests
ایدهٔ کلی: ساخت یک دیکشنری proxies و پاس دادن آن به هر فراخوانی درخواست. این روش روی تمام متدهای HTTP مثل GET، POST، PUT و غیره کار میکند.
import requests
proxies = {
'http': 'http://proxy.example.com:8080',
'https': 'http://proxy.example.com:8081',
}
response = requests.get('http://example.com', proxies=proxies)
print(response.status_code)شرح: ورودیها: دیکشنری proxies که برای هر پروتکل آدرس پروکسی را نگه میدارد. خروجی: یک شیٔ Response از requests که شامل استاتوس، هدرها و متن پاسخ است. خطبهخط: import بارگذاری کتابخانه؛ تعریف proxies؛ فراخوانی requests.get با پارامتر proxies.
احراز هویت پروکسی
دو روش معمول برای ارسال نامکاربری و رمزعبور وجود دارد: قراردادن اعتبارنامه در رشتهٔ پروکسی و یا استفاده از پارامتر auth.
# روش 1: اعتبارنامه در رشتهٔ پروکسی
proxies = {
'http': 'http://USERNAME:PASSWORD@proxy.example.com:8080',
'https': 'http://USERNAME:PASSWORD@proxy.example.com:8081',
}
response = requests.get('http://example.com', proxies=proxies)
# روش 2: استفاده از پارامتر auth
proxies = {
'http': 'http://proxy.example.com:8080',
'https': 'http://proxy.example.com:8081',
}
response = requests.get('http://example.com', proxies=proxies, auth=('USERNAME', 'PASSWORD'))توضیح: گزینهٔ اول ساده است اما نگهداری اعتبارنامه در رشتهها میتواند منجر به نشت اطلاعات شود. گزینهٔ دوم خواناتر است و میتوان اعتبارنامه را از متغیرهای محیطی یا vault خواند. هر دو روش توسط سرور پروکسی پشتیبانی میشوند؛ رفتار دقیق بستگی به ارائهدهنده دارد.
استفاده از Session برای مدیریت ارتباطات
وقتی قصد دارید اتصالها را ماندگار کنید (pooling، کوکیها، هدرها) از requests.Session استفاده کنید. میتوانید پروکسی یا auth را روی session ست کنید تا تمام درخواستها از آن استفاده کنند.
import requests
session = requests.Session()
session.proxies = {
'http': 'http://proxy.example.com:8080',
'https': 'http://proxy.example.com:8081',
}
# یا ست کردن احراز هویت برای تمام درخواستها
session.auth = ('USERNAME', 'PASSWORD')
response = session.get('http://example.com')
print(response.status_code)نکتهٔ مهم: اگر از یک پروکسی ثابت در سشن استفاده کنید و آن پروکسی مسدود شود، همهٔ درخواستها همگی از همان IP مسدود خواهند شد. در این حالت بهتر است از گیتوی پروکسی (که خودِ ارائهدهنده چرخش را انجام میدهد) یا مکانیزم چرخش در کد استفاده کنید.
فرمتهای مرسوم پروکسی و مقایسه
سه فرمت رایج برای دریافت دسترسی به پروکسی وجود دارد:
- لیست IPهای پروکسی — شما یک لیست خام از آدرسها میگیرید و خودتان باید بچرخانید.
- گیتوی پروکسی — یک آدرس واحد که ارائهدهنده پشتصحنه پروکسیها را مدیریت میکند.
- API پروکسی — ارسال URL به یک endpoint و دریافت خودِ HTML یا نتیجه؛ ارائهدهنده تمام مدیریت را انجام میدهد.
مزایا/معایب کلی:
- لیست IP: کنترل کامل ولی نیاز به نظارت و حذف IPهای مرده.
- گیتوی: پیادهسازی ساده، مناسب وقتی نیاز به چرخش توسط ارائهدهنده دارید.
- API: سادهترین مدل برای توسعهدهنده، اما ممکن است هزینه و محدودیتهای بیشتری داشته باشد.
ادغام ۱ — چرخش از لیست پروکسیها
ایدهٔ کلی: با هر درخواست یک پروکسی تصادفی (یا دورهای) انتخاب کنید و ارسال کنید. در عمل نیاز است پروکسیها را مانیتور کنید و IPهای بد را حذف کنید.
import requests
import random
import time
from requests.exceptions import RequestException
proxy_list = [
'http://Username:Password@85.237.57.198:20000',
'http://Username:Password@85.237.57.198:21000',
'http://Username:Password@85.237.57.198:22000',
'http://Username:Password@85.237.57.198:23000',
]
def fetch(url, max_retries=3):
for attempt in range(max_retries):
proxy = random.choice(proxy_list)
proxies = { 'http': proxy, 'https': proxy }
try:
r = requests.get(url, proxies=proxies, timeout=10)
r.raise_for_status()
return r.text
except RequestException as e:
# لاگ خطا، حذف یا نشانهگذاری پروکسی در سیستم مانیتورینگ
print(f'Proxy failed: {proxy} — {e}')
time.sleep(1 + attempt)
raise RuntimeError('All proxies failed')
html = fetch('https://example.com')
print(len(html))توضیح: ورودی تابع fetch یک URL است؛ خروجی متن HTML صفحه یا استثنایی که نشاندهندهٔ شکست است. خطبهخط: انتخاب پروکسی با random.choice، تنظیم timeout جهت جلوگیری از بلوکه شدن، استفاده از raise_for_status برای تبدیل پاسخهای HTTP خطادار به استثناء، و retry با backoff ساده.
بهترینروشها: پروکسیهای کند را با معیارهای latency حذف کنید، از یک دیتابیس یا سرویس مانیتورینگ برای وضعیت پروکسیها استفاده کنید و هرگز credentialها را در سورس کنترل ذخیره نکنید.
ادغام ۲ — گیتوی پروکسی (Proxy Gateway)
در این مدل یک آدرس واحد دریافت میکنید و ارائهدهنده خودش چرخش و نگهداری استخر را انجام میدهد؛ مناسب برای residential یا mobile pools.
import requests
proxies = {
'http': 'http://zproxy.example-gateway.io:22225',
'https': 'http://zproxy.example-gateway.io:22225',
}
response = requests.get('http://example.com', proxies=proxies, auth=('USERNAME', 'PASSWORD'))
print(response.status_code)
توضیح: این روش سادهترین پیادهسازی است؛ ورودیها: آدرس گیتوی و اعتبارنامه، خروجی: پاسخ دریافتی از هدف. نکته: ممکن است ارائهدهنده گزینههایی برای انتخاب شهر، کشور یا نوع آیپی (residential/datacenter) با پارامترهای احراز هویت یا هدرها در اختیار بگذارد.
ادغام ۳ — API پروکسی
با API پروکسی شما معمولاً URL هدف را به endpoint ارائهدهنده میفرستید و او HTML حاصل را برایتان بازمیگرداند. مزیت: نیازی به مدیریت هدرها، کوکیها یا چرخش پیچیده ندارید.
import requests
from urllib.parse import urlencode
payload = {
'api_key': 'APIKEY',
'url': 'https://httpbin.org/ip',
}
# گزینهٔ ساده با params
r = requests.get('https://proxy.example-api.io/v1/', params=payload, timeout=30)
print(r.text)
# یا ساخت دستی URL-encoded (مهم وقتی پارامترها پیچیدهاند)
qs = urlencode(payload)
r2 = requests.get('https://proxy.example-api.io/v1/?' + qs, timeout=30)
print(r2.status_code)
نکتهٔ مهم دربارهٔ URL encoding: اگر URL هدف پارامتر query داشته باشد، باید آن را کدگذاری کنید تا پارامترهای هدف با پارامترهای API تداخل نکند. استفاده از urlencode یا ارسال دیکشنری در params معمولاً کافی است.
نکات عملکرد، امنیت و پایداری
- همیشه timeout مشخص کنید تا نخها یا فرایندها بلوکه نشوند.
- از retry و backoff برای مقابله با ناپایداری شبکه استفاده کنید.
- اعتبارنامهها را در متغیرهای محیطی یا secret manager نگهداری کنید، نه در کد.
- برای مقیاسپذیری، وضعیت هر پروکسی را مانیتور و امتیازدهی کنید (latency، rate limit، error rate).
- برای کاهش ریسک بلوک شدن، هدرها، تاخیر بین درخواستها و الگوی user-agent را متنوع کنید.
- از session برای pooling استفاده کنید تا هزینهٔ اتصال کاهش یابد؛ اما در صورت استفاده از proxy ثابت مراقب مسدود شدن گسترده باشید.
- قوانین سایتها و ملاحظات اخلاقی/قانونی را رعایت کنید؛ scraping بدون اجازه ممکن است منجر به عواقب حقوقی شود.
جمعبندی
پروکسیها ابزار مهمی برای اسکریپینگ در مقیاس هستند. با Python Requests میتوانید بهسادگی پروکسیهای ساده، پروکسیهای دارای احراز هویت، سشنهای دارای پروکسی و روشهای پیچیدهتر مثل گیتوی یا API را پیاده کنید. مهمترین توصیهها: از timeout و retry استفاده کنید، credentialها را امن نگه دارید و پروکسیها را مانیتور کنید تا تجربهٔ پایداری در اسکریپینگ داشته باشید.





