الخطأ الكلاسيكي عند توسيع أداة التجريف هو شراء البروكسيات "بالعين": أخذنا 100 IP، أطلقنا أداة التجريف، حصلنا على حظر بعد نصف ساعة. المشكلة ليست في عدد العناوين، بل في أن لا أحد يحسب الحمل الحقيقي على كل IP. سنقوم بتحليل صيغة حساب مجموعة البروكسيات، المعتمدة على RPS (طلبات في الثانية)، التأخيرات والحدود الخاصة بالموقع المستهدف — مع أرقام محددة وكود بلغة بايثون.
لماذا حساب المجموعة حسب عدد IP هو خطأ
النهج النموذجي للمبتدئين في التجريف: "يجب جمع 50,000 بطاقة منتج، لذا سنشتري 500 بروكسي ونوزع الحمل". تبدو المنطق صحيحة، لكنها لا تأخذ في الاعتبار الأهم — المواقع مثل Wildberries و Ozon تحظر ليس بناءً على العدد المطلق للطلبات، بل بناءً على شدة الطلبات من IP واحد في وحدة الزمن. بمعنى آخر، 500 بروكسي، كل منها يرسل 20 طلبًا في الثانية، سيتم حظرها على الفور — أنظمة مكافحة الروبوتات ترى نمطًا مشابهًا لهجوم DDoS.
من ناحية أخرى، إذا كان لديك 50 بروكسي، لكن كل واحد يقوم بإرسال طلب واحد كل 5-10 ثوانٍ مع فترات توقف عشوائية، مقلدًا سلوك الإنسان، يمكنك التجريف بشكل مستقر لأسابيع دون حظر واحد. عدد IP ليس سبب الاستقرار، بل نتيجة لحساب الحمل بشكل صحيح. لهذا السبب يجب أن تستند الصيغة إلى "كم عدد IP يجب شراؤها"، بل إلى "كم عدد RPS يجب تحقيقه وما هي الحمل الآمن على 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 واحد يمكنه فعليًا إصدار طلب واحد فقط كل 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 ثانية). إذا كان كل بطاقة تحتاج إلى طلب واحد، فإن 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 منتج كل ساعتين. 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 في الوقت الحقيقي. 5000 إعلان، تحديث كل 15 دقيقة. RPS_target = 5000 / 900 ≈ 5.56 RPS. مع فترة 8 ثوانٍ: N = (5.56 × 8) / 1 ≈ 45 بروكسي. من المهم أن تأخذ في الاعتبار أن Avito تحظر بنشاط شبكات مراكز البيانات، لذا من الأفضل في هذه الحالة استخدام IP سكنية أو محمولة.
البروكسيات السكنية، المحمولة ومراكز البيانات في الصيغة
نوع البروكسي يؤثر مباشرة على Delay_per_ip وبالتالي على N النهائي في الصيغة. البروكسيات من مراكز البيانات أرخص وأسرع، لكنها تتطلب فترات أطول بين الطلبات وغالبًا ما تُحظر عند زيادة التكرار — في الواقع، قد تحتاج إلى 2-3 مرات أكثر من IP من مراكز البيانات لتحقيق نفس 5 RPS مقارنة بالبروكسيات السكنية.
| نوع البروكسي | متوسط Delay_per_ip | متى تستخدم |
|---|---|---|
| بروكسي مراكز البيانات | 8-15 ثوانٍ | APIs مفتوحة، مواقع بدون حماية صارمة ضد الروبوتات |
| بروكسي سكنية | 4-8 ثوانٍ | Wildberries، Ozon، Avito وأسواق أخرى مع حماية ضد الروبوتات |
| بروكسي محمولة | 3-6 ثوانٍ | أكثر الحمايات عدوانية، الشبكات الاجتماعية، APIs المحمولة |
للتجريف من أسواق مثل Wildberries و Ozon، عادة ما تكون البروكسيات السكنية هي الخيار الأمثل — حيث توازن بين السعر والاستقرار، مما يسمح بفترات أقصر دون زيادة حادة في الحظرات. يجب النظر في البروكسيات من مراكز البيانات فقط للمواقع التي لا تحتوي على حماية صارمة ضد الروبوتات أو للمهام الفردية ذات RPS منخفض.
تنفيذ المجموعة بلغة بايثون: كود مع التدوير
أدناه — تنفيذ مبسط لمجموعة البروكسيات مع التحكم في تكرار الطلبات لكل 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.