اشتباه کلاسیک در مقیاسگذاری پارسر — خرید پروکسی "به چشم": 100 IP خریدیم، پارسر را راهاندازی کردیم و بعد از نیم ساعت بن شدیم. مشکل در تعداد آدرسها نیست، بلکه در این است که هیچکس بار واقعی روی هر IP را محاسبه نمیکند. فرمول محاسبه استخر پروکسی را بررسی میکنیم که بر اساس RPS (درخواستها در ثانیه)، تأخیرها و محدودیتهای وبسایت هدف است — با اعداد خاص و کد در Python.
چرا محاسبه استخر بر اساس تعداد IP اشتباه است
رویکرد معمولی یک مبتدی در پارسینگ: "باید 50,000 کارت کالا جمعآوری کنیم، پس 500 پروکسی میخریم و بار را توزیع میکنیم". منطق به نظر منطقی میرسد، اما مهمترین نکته را در نظر نمیگیرد — وبسایتهایی مانند Wildberries و Ozon بر اساس شدت درخواستها از یک IP در واحد زمان بن میکنند، نه بر اساس تعداد مطلق درخواستها. به عبارت دیگر، 500 پروکسی که هر کدام 20 درخواست در ثانیه ارسال میکنند، به سرعت بن میشوند — سیستمهای ضد ربات الگوی مشابهی به DDoS را شناسایی میکنند.
از طرف دیگر، اگر شما 50 پروکسی داشته باشید، اما هر کدام 1 درخواست در 5-10 ثانیه با وقفههای تصادفی ارسال کنند و رفتار انسانی را شبیهسازی کنند، میتوانید به طور پایدار هفتهها بدون هیچ بنی پارس کنید. تعداد IP دلیل ثبات نیست، بلکه نتیجه بار محاسبه شده به درستی است. به همین دلیل فرمول باید از "چند IP بخریم" به "چند RPS باید به دست آوریم و بار ایمن برای یک IP چقدر است" تغییر کند.
نکته دیگری که باید در نظر گرفت: انواع مختلف پروکسی دارای "مقاومت" متفاوتی برای یک IP هستند. پروکسیهای دیتاسنتری سریعتر در صورت افزایش فرکانس درخواستها بن میشوند، زیرا زیرشبکههای آنها به راحتی به عنوان هاستینگ شناسایی میشوند. IPهای مسکونی و موبایلی مانند کاربران عادی به نظر میرسند و میتوانند کمی فرکانس بالاتری را بدون خطر بن شدن تحمل کنند — اما این به این معنی نیست که میتوان محدودیتها را به طور کامل نادیده گرفت.
فرمول پایه محاسبه استخر پروکسی
فرمول محاسبه تعداد پروکسی در استخر به شکل زیر است:
N = (RPS_target × Delay_per_ip) / Concurrency_per_ip
که در آن:
- N — تعداد مورد نیاز پروکسی در استخر؛
- RPS_target — سرعت هدف پارسینگ (درخواستها در ثانیه در کل سیستم)؛
- Delay_per_ip — حداقل وقفه ایمن بین درخواستها از یک IP (به ثانیه)؛
- Concurrency_per_ip — چند جریان موازی را برای یک IP مجاز میدانید (معمولاً 1، حداکثر 2 برای پروکسیهای مسکونی).
منطق ساده است: اگر میخواهید در مجموع 10 درخواست در ثانیه داشته باشید و وقفه ایمن بین درخواستها از یک IP 8 ثانیه باشد، یک IP به طور فیزیکی فقط میتواند 1 درخواست در 8 ثانیه ارسال کند، یعنی 0.125 RPS. برای به دست آوردن 10 RPS در مجموع، به 10 / 0.125 = 80 پروکسی نیاز دارید. این همان محاسبهای است که جایگزین حدس "500 IP به هر دلیلی" میشود.
چگونه RPS هدف برای پارسینگ را محاسبه کنیم
قبل از محاسبه استخر، باید RPS_target را تعیین کنید — چند درخواست در ثانیه واقعاً نیاز دارید تا دادهها را در زمان معقولی جمعآوری کنید. فرمول در اینجا معکوس است:
RPS_target = Total_requests / Time_budget_seconds
مثال: باید 100,000 کارت کالا از Wildberries را در 8 ساعت (28,800 ثانیه) جمعآوری کنید. اگر برای هر کارت 1 درخواست لازم باشد، RPS_target = 100,000 / 28,800 ≈ 3.47 درخواست در ثانیه. این به اندازهای که در ابتدا به نظر میرسد زیاد نیست — بسیاری سرعت مورد نیاز را بیش از حد تخمین میزنند و تعداد زیادی پروکسی میخرند.
اگر وظیفه شامل چند نوع درخواست باشد (به عنوان مثال، ابتدا لیست دستهها را دریافت کنید، سپس کارتها، سپس نظرات)، RPS را برای هر مرحله به طور جداگانه محاسبه کنید — آنها میتوانند به طور موازی با استخرهای پروکسی مختلف پیش بروند و بار کلی بر روی پلتفرم بین نقاط انتهایی مختلف توزیع شود.
محدودیتها برای یک IP: چند درخواست در دقیقه ایمن است
Delay_per_ip — مهمترین پارامتر در فرمول است و باید به صورت تجربی برای هر وبسایت تعیین شود. نشانههای عمومی، بر اساس تجربه پارسینگ بازارها:
| پلتفرم | وقفه ایمن بین درخواستها از 1 IP | حداکثر درخواستها/دقیقه از 1 IP |
|---|---|---|
| Wildberries (API کارتها) | 4-6 ثانیه | 10-15 |
| Ozon (صفحات کالاها) | 5-8 ثانیه | 8-12 |
| Avito (آگهیها) | 6-10 ثانیه | 6-10 |
| Yandex.Market | 5-7 ثانیه | 8-12 |
این اعداد نقطه شروع هستند، نه یک قانون مطلق. با مقادیر محافظهکارانه (حد بالای وقفه) شروع کنید، درصد خطاهای 429 و 403 را زیر نظر داشته باشید و به تدریج وقفه را کاهش دهید اگر بنها افزایش نیابند. افزایش ناگهانی RPS بدون آزمایش تدریجی — رایجترین روش برای از بین بردن کل استخر پروکسی در یک روز است.
محاسبات عملی: Wildberries، Ozon، Avito
سه سناریوی واقعی را با محاسبه کامل بر اساس فرمول بررسی میکنیم.
سناریو 1: نظارت بر قیمتها در Wildberries. نیاز به بهروزرسانی قیمت 20,000 کالا هر 2 ساعت. RPS_target = 20,000 / (2 × 3600) ≈ 2.78 RPS. با وقفه 5 ثانیه برای 1 IP و Concurrency = 1: N = (2.78 × 5) / 1 ≈ 14 پروکسی. برای احتیاط در صورت بن شدن بخشی از IPها، توصیه میشود استخر با ضریب 1.5-2x، یعنی 21-28 پروکسی تهیه کنید.
سناریو 2: جمعآوری یکباره کاتالوگ Ozon. 500,000 کارت در 24 ساعت. RPS_target = 500,000 / 86,400 ≈ 5.79 RPS. با وقفه 6 ثانیه: N = (5.79 × 6) / 1 ≈ 35 پروکسی. با احتیاط — 50-60 پروکسی.
سناریو 3: نظارت بر رقبا در Avito به صورت زنده. 5,000 آگهی، بهروزرسانی هر 15 دقیقه. RPS_target = 5,000 / 900 ≈ 5.56 RPS. با وقفه 8 ثانیه: N = (5.56 × 8) / 1 ≈ 45 پروکسی. در اینجا مهم است که در نظر داشته باشید که Avito به شدت زیرشبکههای دیتاسنتری را شناسایی میکند، بنابراین برای چنین وظیفهای بهتر است از IPهای مسکونی یا موبایلی استفاده کنید.
پروکسیهای مسکونی، موبایلی و دیتاسنتری در فرمول
نوع پروکسی به طور مستقیم بر Delay_per_ip و به تبع آن بر N نهایی در فرمول تأثیر میگذارد. پروکسیهای دیتاسنتری ارزانتر و سریعتر هستند، اما نیاز به وقفههای طولانیتری بین درخواستها دارند و در صورت افزایش فرکانس بیشتر بن میشوند — در واقع، برای همان 5 RPS ممکن است به 2-3 برابر IPهای دیتاسنتری بیشتر از IPهای مسکونی نیاز داشته باشید.
| نوع پروکسی | میانگین Delay_per_ip | کی استفاده کنیم |
|---|---|---|
| پروکسیهای دیتاسنتری | 8-15 ثانیه | APIهای باز، وبسایتهای بدون ضد ربات سخت |
| پروکسیهای مسکونی | 4-8 ثانیه | Wildberries، Ozon، Avito و سایر بازارها با ضد ربات |
| پروکسیهای موبایلی | 3-6 ثانیه | محافظتهای بسیار تهاجمی، شبکههای اجتماعی، APIهای موبایلی |
برای پارسینگ بازارهایی مانند Wildberries و Ozon، معمولاً بهترین انتخاب پروکسیهای مسکونی هستند — آنها قیمت و ثبات را متعادل میکنند و اجازه میدهند وقفههای کوتاهتری بدون افزایش ناگهانی بنها داشته باشید. پروکسیهای دیتاسنتری تنها باید برای وبسایتهای بدون ضد ربات تهاجمی یا برای وظایف یکباره با RPS پایین در نظر گرفته شوند.
پیادهسازی استخر در Python: کد با چرخش
در زیر — پیادهسازی سادهای از استخر پروکسی با کنترل فرکانس درخواستها برای هر IP. منطق: هر پروکسی زمان آخرین استفاده را ذخیره میکند و برنامهریز تنها IPهایی را انتخاب میکند که زمان کافی از آخرین درخواست گذشته باشد.
import time
import random
from dataclasses import dataclass, field
from typing import List, Optional
@dataclass
class ProxyNode:
address: str
delay_per_ip: float # وقفه ایمن به ثانیه
last_used: float = field(default=0.0)
class ProxyPool:
def __init__(self, proxies: List[str], delay_per_ip: float):
self.nodes = [ProxyNode(address=p, delay_per_ip=delay_per_ip) for p in proxies]
def get_available_proxy(self) -> Optional[ProxyNode]:
now = time.time()
available = [
node for node in self.nodes
if now - node.last_used >= node.delay_per_ip
]
if not available:
return None
# انتخاب تصادفی از موجودها، برای جلوگیری از الگوی صف
node = random.choice(available)
node.last_used = now
return node
def size(self) -> int:
return len(self.nodes)
def calculate_pool_size(rps_target: float, delay_per_ip: float, concurrency: int = 1) -> int:
"""فرمول: N = (RPS_target * Delay_per_ip) / Concurrency_per_ip"""
return max(1, int((rps_target * delay_per_ip) / concurrency))
# مثال استفاده
rps_target = 5.79 # محاسبه شده از حجم وظیفه و زمان
delay_per_ip = 6.0 # وقفه ایمن برای Ozon
n_proxies = calculate_pool_size(rps_target, delay_per_ip)
print(f"پروکسیهای مورد نیاز در استخر: {n_proxies}") # ~35، با احتیاط 50-60
در یک پارسر واقعی، این منطق باید با صف وظایف (به عنوان مثال، از طریق asyncio یا multiprocessing) تکمیل شود، تا کارگران منتظر ظهور پروکسی آزاد باشند، نه اینکه در صورت عدم وجود آنها با خطا مواجه شوند. همچنین باید یک backoff نمایی در صورت دریافت 429/403 اضافه کنید — این به طور خودکار وقفه را برای IP خاصی در صورت نشانههای مسدود شدن افزایش میدهد.
نظارت و اصلاح دینامیک استخر
محاسبه ثابت بر اساس فرمول — نقطه شروع است، نه راهحل نهایی. در استفاده واقعی، باید سه معیار کلیدی را زیر نظر داشته باشید:
- نرخ موفقیت — درصد درخواستهای موفق (کد 200) از کل تعداد. کاهش به زیر 90-95% نشاندهنده این است که Delay_per_ip باید افزایش یابد یا پروکسی بیشتری به استخر اضافه شود؛
- نرخ بن — سهم پروکسیهایی که نشانههای مسدود شدن (کپچا، 403، ریدایرکت به فرم تأیید) را در ساعت گذشته نشان دادهاند؛
- RPS واقعی — سرعت واقعی پردازش درخواستها که ممکن است به دلیل تایماوتها و تلاشهای مجدد با محاسبه متفاوت باشد.
قاعده عملی: اگر نرخ بن در هر ساعت بیش از 5-7% باشد، Delay_per_ip را 20-30% افزایش دهید و N را دوباره با فرمول محاسبه کنید. اگر نرخ موفقیت به طور پایدار بالای 98% برای چند ساعت باشد، میتوانید به تدریج وقفه را کاهش داده و اندازه استخر را کاهش دهید — این یک صرفهجویی مستقیم در بودجه پروکسی بدون از دست دادن ثبات است.
یک روش خوب این است که برای هر IP به طور جداگانه لاگ نگه دارید: زمان آخرین درخواست موفق، تعداد خطاهای متوالی، میانگین زمان پاسخ. این به طور خودکار به شما اجازه میدهد که پروکسیهای "خراب" را به مدت 30-60 دقیقه از چرخش خارج کنید به جای اینکه به ارسال درخواستها از طریق آنها ادامه دهید و در هر مرحله کپچا دریافت کنید.
اشتباهات رایج در محاسبه استخر پروکسی
حتی با دانستن فرمول، راحت است که در جزئیات محاسبه اشتباه کنید. در اینجا فهرستی از اشتباهات رایج آورده شده است:
- نادیده گرفتن احتیاط برای بنها. حتی با محاسبه ایدهآل، 5-10% پروکسیها به دلیل مسدود شدن یا مشکلات شبکه به طور موقت در دسترس نخواهند بود. همیشه یک ضریب 1.3-2x به N پایه اضافه کنید؛
- Delay_per_ip یکسان برای تمام نقاط انتهایی. صفحه دسته و صفحه کارت کالا ممکن است محدودیتهای متفاوتی داشته باشند — به طور جداگانه محاسبه کنید؛
- Concurrency بیشتر از 1 بدون آزمایش. درخواستهای موازی از یک IP به شدت خطر بن شدن را افزایش میدهد، به ویژه در پروکسیهای مسکونی — با Concurrency = 1 شروع کنید؛
- عدم چرخش User-Agent و هدرها. حتی استخر پروکسی به درستی محاسبه شده نیز نجات نمیدهد اگر همه درخواستها با یک اثر انگشت مرورگر ارسال شوند؛
- وقفه ثابت بدون جیتتر. فاصله کاملاً یکسان بین درخواستها (به عنوان مثال، دقیقاً 5.0 ثانیه) — این یک الگو است که به راحتی توسط ضد ربات شناسایی میشود. انحراف تصادفی ±20-30% اضافه کنید.
نتیجهگیری
فرمول N = (RPS_target × Delay_per_ip) / Concurrency_per_ip محاسبه استخر پروکسی را از حدس به یک وظیفه مهندسی با اعداد مشخص تبدیل میکند. ابتدا سرعت هدف پارسینگ را بر اساس حجم دادهها و زمان تعیین کنید، سپس به صورت تجربی وقفه ایمن را برای وبسایت خاص پیدا کنید و تنها پس از آن تعداد IP مورد نیاز را محاسبه کنید — با احتیاط 30-100% برای بنها و اختلالات.
این رویکرد بودجه را صرفهجویی میکند: به جای خرید تعداد زیادی IP "به هر دلیلی"، شما دقیقاً برای حجم پروکسی که برای دستیابی به RPS هدف بدون خطر مسدود شدن نیاز دارید، پرداخت میکنید. برای پارسینگ بازارها و سایر وبسایتهای محافظت شده، توصیه میکنیم با پروکسیهای مسکونی شروع کنید — آنها بهترین تعادل بین ثبات و هزینه را در کار با سیستمهای ضد ربات Wildberries، Ozon و Avito ارائه میدهند.