العودة إلى المدونة

كيفية تجنب الحظر عند إجراء طلبات جماعية

نستعرض آليات اكتشاف الأتمتة وتقنيات محددة للحماية من الحظر عند الطلبات الجماعية: من التدوير الأساسي للبروكسي إلى محاكاة سلوك الإنسان.

📅١ رجب ١٤٤٧ هـ
```html

الحماية من الحظر عند إجراء طلبات جماعية: التقنيات والأدوات

حظر الحسابات وعناوين IP هي المشكلة الرئيسية عند الزحف، الأتمتة والعمليات الجماعية على وسائل التواصل الاجتماعي. تقوم أنظمة مكافحة الروبوتات الحديثة بتحليل عشرات المعلمات: من تكرار الطلبات إلى بصمات المتصفح. في هذا الدليل، سنحلل آليات اكتشاف الأتمتة وطرق عملية لتجاوزها.

آليات اكتشاف الأتمتة

تستخدم أنظمة الحماية الحديثة تحليل متعدد المستويات لاكتشاف الروبوتات. فهم هذه الآليات أمر بالغ الأهمية لاختيار الاستراتيجية الصحيحة للتجاوز.

المعلمات الأساسية للتحليل

سمعة IP: تتحقق أنظمة مكافحة الروبوتات من تاريخ عنوان IP، والانتماء لمراكز البيانات، وما إذا كان موجودًا في القوائم السوداء. يتم حظر IP من مجموعات الوكلاء المعروفة بشكل متكرر.

تكرار الطلبات (Request Rate): لا يمكن للإنسان إرسال 100 طلب في الدقيقة جسديًا. تقوم الأنظمة بتحليل ليس فقط العدد الإجمالي، ولكن أيضًا التوزيع الزمني - الفواصل الزمنية المتساوية بين الطلبات تكشف عن الروبوت.

أنماط السلوك: تسلسل الإجراءات، عمق التمرير، حركات الفأرة، الوقت على الصفحة. يتم التعرف بسهولة على الروبوت الذي ينتقل بين الروابط دون تأخير.

بصمات تقنية: User-Agent، رؤوس HTTP، ترتيب الرؤوس، بصمة TLS، بصمة Canvas/WebGL. عدم التطابق في هذه المعلمات هو علامة حمراء لأنظمة مكافحة الروبوتات.

المعلمة ما يتم تحليله خطر الاكتشاف
عنوان IP السمعة، ASN، الموقع الجغرافي مرتفع
User-Agent إصدار المتصفح، نظام التشغيل، الجهاز متوسط
بصمة TLS مجموعة التشفير، الامتدادات مرتفع
بصمة HTTP/2 ترتيب الرؤوس، الإعدادات مرتفع
Canvas/WebGL رسم الرسوميات متوسط
السلوك النقرات، التمرير، الوقت مرتفع

تحديد معدل الطلبات والتحكم في تكرار الطلبات

التحكم في سرعة إرسال الطلبات هو الخط الدفاعي الأول ضد الحظر. حتى مع تدوير الوكلاء، فإن الزحف العدواني للغاية سيؤدي إلى الحظر.

التأخيرات الديناميكية

الفواصل الزمنية الثابتة (مثل دقيقتين بالضبط بين الطلبات) يمكن التعرف عليها بسهولة. استخدم تأخيرات عشوائية مع توزيع طبيعي:

import time
import random
import numpy as np

def human_delay(min_delay=1.5, max_delay=4.0, mean=2.5, std=0.8):
    """
    توليد تأخير مع توزيع طبيعي
    يحاكي سلوك الإنسان
    """
    delay = np.random.normal(mean, std)
    # نحدد النطاق
    delay = max(min_delay, min(delay, max_delay))
    
    # نضيف تأخيرات صغيرة للواقعية
    delay += random.uniform(0, 0.3)
    
    time.sleep(delay)

# الاستخدام
for url in urls:
    response = session.get(url)
    human_delay(min_delay=2, max_delay=5, mean=3, std=1)

تحديد معدل الطلبات التكيفي

نهج أكثر تقدمًا هو تعديل السرعة بناءً على ردود الخادم. إذا كنت تتلقى رموز 429 (طلبات كثيرة جدًا) أو 503، قلل السرعة تلقائيًا:

class AdaptiveRateLimiter:
    def __init__(self, initial_delay=2.0):
        self.current_delay = initial_delay
        self.min_delay = 1.0
        self.max_delay = 30.0
        self.error_count = 0
        
    def wait(self):
        time.sleep(self.current_delay + random.uniform(0, 0.5))
        
    def on_success(self):
        # نسرع تدريجياً عند الطلبات الناجحة
        self.current_delay = max(
            self.min_delay, 
            self.current_delay * 0.95
        )
        self.error_count = 0
        
    def on_rate_limit(self):
        # نبطئ بشكل حاد عند الحظر
        self.error_count += 1
        self.current_delay = min(
            self.max_delay,
            self.current_delay * (1.5 + self.error_count * 0.5)
        )
        print(f"تم الوصول إلى حد المعدل. التأخير الجديد: {self.current_delay:.2f} ثواني")

# التطبيق
limiter = AdaptiveRateLimiter(initial_delay=2.0)

for url in urls:
    limiter.wait()
    response = session.get(url)
    
    if response.status_code == 429:
        limiter.on_rate_limit()
        time.sleep(60)  # توقف قبل إعادة المحاولة
    elif response.status_code == 200:
        limiter.on_success()
    else:
        # معالجة الأخطاء الأخرى
        pass

نصيحة عملية: تختلف السرعة المثلى لمواقع مختلفة. المنصات الكبيرة (Google، Facebook) تتحمل 5-10 طلبات في الدقيقة من IP واحد. قد تحظر المواقع الصغيرة بالفعل عند 20-30 طلبًا في الساعة. ابدأ دائمًا بحذر وزد الحمل تدريجيًا، مع تتبع نسبة الأخطاء.

تدوير الوكلاء وإدارة عناوين IP

استخدام عنوان IP واحد للطلبات الجماعية يضمن الحظر. تدوير الوكلاء يوزع الحمل ويقلل من خطر الاكتشاف.

استراتيجيات التدوير

1. تدوير حسب الطلبات: تغيير IP بعد كل طلب أو كل N طلبات. مناسب لزحف محركات البحث حيث تكون خصوصية كل طلب مهمة.

2. تدوير حسب الوقت: تغيير IP كل 5-15 دقيقة. فعالة للعمل مع وسائل التواصل الاجتماعي حيث تكون استقرار الجلسة مهمة.

3. جلسات لزجة: استخدام IP واحد لكامل جلسة المستخدم (تسجيل الدخول، تسلسل الإجراءات). حاسم للمواقع التي تحتوي على حماية ضد CSRF.

import requests
from itertools import cycle

class ProxyRotator:
    def __init__(self, proxy_list, rotation_type='request', rotation_interval=10):
        """
        rotation_type: 'request' (كل طلب) أو 'time' (حسب الوقت)
        rotation_interval: عدد الطلبات أو الثواني
        """
        self.proxies = cycle(proxy_list)
        self.current_proxy = next(self.proxies)
        self.rotation_type = rotation_type
        self.rotation_interval = rotation_interval
        self.request_count = 0
        self.last_rotation = time.time()
        
    def get_proxy(self):
        if self.rotation_type == 'request':
            self.request_count += 1
            if self.request_count >= self.rotation_interval:
                self.current_proxy = next(self.proxies)
                self.request_count = 0
                print(f"تم التدوير إلى: {self.current_proxy}")
                
        elif self.rotation_type == 'time':
            if time.time() - self.last_rotation >= self.rotation_interval:
                self.current_proxy = next(self.proxies)
                self.last_rotation = time.time()
                print(f"تم التدوير إلى: {self.current_proxy}")
                
        return {'http': self.current_proxy, 'https': self.current_proxy}

# مثال على الاستخدام
proxy_list = [
    'http://user:pass@proxy1.example.com:8000',
    'http://user:pass@proxy2.example.com:8000',
    'http://user:pass@proxy3.example.com:8000',
]

rotator = ProxyRotator(proxy_list, rotation_type='request', rotation_interval=5)

for url in urls:
    proxies = rotator.get_proxy()
    response = requests.get(url, proxies=proxies, timeout=10)

اختيار نوع الوكيل

نوع الوكيل مستوى الثقة السرعة الاستخدام
مراكز البيانات منخفض مرتفع زحف بسيط، API
سكنية مرتفع متوسط وسائل التواصل الاجتماعي، المواقع المحمية
محمول مرتفع جدًا متوسط Instagram، TikTok، مكافحة الاحتيال

للعمليات الجماعية على وسائل التواصل الاجتماعي وعلى المنصات ذات الحماية الشديدة، استخدم وكلاء سكنيين. تبدو وكأنها اتصالات منزلية عادية ونادرًا ما يتم إدراجها في القوائم السوداء. مراكز البيانات مناسبة للموارد الأقل حماية، حيث تكون السرعة مهمة.

بصمة المتصفح وبصمات TLS

حتى مع تدوير IP، يمكن اكتشافك من خلال بصمات التقنية للمتصفح واتصال TLS. هذه المعلمات فريدة لكل عميل وصعبة التزوير.

بصمة TLS

عند إنشاء اتصال HTTPS، يرسل العميل ClientHello مع مجموعة من التشفيرات والامتدادات المدعومة. هذه المجموعة فريدة لكل مكتبة. على سبيل المثال، تستخدم مكتبة Python requests OpenSSL، والتي يمكن تمييز بصمتها بسهولة عن Chrome.

المشكلة: المكتبات القياسية (requests، urllib، curl) لديها بصمات تختلف عن المتصفحات الحقيقية. تستخدم خدمات مثل Cloudflare وAkamai وDataDome بنشاط بصمة TLS لحظر الروبوتات.

الحل: استخدم المكتبات التي تحاكي بصمات TLS للمتصفحات. بالنسبة لـ Python، يمكن استخدام curl_cffi أو tls_client أو playwright/puppeteer لمحاكاة المتصفح بشكل كامل.

# التثبيت: pip install curl-cffi
from curl_cffi import requests

# محاكاة Chrome 110
response = requests.get(
    'https://example.com',
    impersonate="chrome110",
    proxies={'https': 'http://proxy:port'}
)

# بديل: tls_client
import tls_client

session = tls_client.Session(
    client_identifier="chrome_108",
    random_tls_extension_order=True
)

response = session.get('https://example.com')

بصمة HTTP/2

بالإضافة إلى TLS، تقوم أنظمة مكافحة الروبوتات بتحليل معلمات HTTP/2: ترتيب الرؤوس، إعدادات إطار SETTINGS، أولويات التدفقات. لا تلتزم المكتبات القياسية بالترتيب الدقيق للرؤوس في Chrome أو Firefox.

# الترتيب الصحيح للرؤوس لـ Chrome
headers = {
    ':method': 'GET',
    ':authority': 'example.com',
    ':scheme': 'https',
    ':path': '/',
    'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120"',
    'sec-ch-ua-mobile': '?0',
    'sec-ch-ua-platform': '"Windows"',
    'upgrade-insecure-requests': '1',
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)...',
    'accept': 'text/html,application/xhtml+xml...',
    'sec-fetch-site': 'none',
    'sec-fetch-mode': 'navigate',
    'sec-fetch-user': '?1',
    'sec-fetch-dest': 'document',
    'accept-encoding': 'gzip, deflate, br',
    'accept-language': 'en-US,en;q=0.9',
}

بصمة Canvas وWebGL

تقوم المتصفحات برسم الرسوميات بطرق مختلفة اعتمادًا على GPU، برامج التشغيل ونظام التشغيل. تستخدم المواقع ذلك لإنشاء بصمة فريدة للجهاز. عند استخدام المتصفحات بدون رأس (Selenium، Puppeteer)، من المهم إخفاء علامات الأتمتة:

// Puppeteer: إخفاء وضع الرأس
const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');

puppeteer.use(StealthPlugin());

const browser = await puppeteer.launch({
    headless: true,
    args: [
        '--disable-blink-features=AutomationControlled',
        '--no-sandbox',
        '--disable-setuid-sandbox',
        `--proxy-server=${proxyUrl}`
    ]
});

const page = await browser.newPage();

// إعادة تعريف navigator.webdriver
await page.evaluateOnNewDocument(() => {
    Object.defineProperty(navigator, 'webdriver', {
        get: () => false,
    });
});

الرؤوس، الكوكيز وإدارة الجلسات

العمل الصحيح مع رؤوس HTTP والكوكيز أمر حاسم لمحاكاة المستخدم الحقيقي. الأخطاء في هذه المعلمات هي سبب شائع للحظر.

الرؤوس الإلزامية

الحد الأدنى من مجموعة الرؤوس لمحاكاة متصفح Chrome:

import requests

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
    'Accept-Language': 'en-US,en;q=0.9',
    'Accept-Encoding': 'gzip, deflate, br',
    'DNT': '1',
    'Connection': 'keep-alive',
    'Upgrade-Insecure-Requests': '1',
    'Sec-Fetch-Dest': 'document',
    'Sec-Fetch-Mode': 'navigate',
    'Sec-Fetch-Site': 'none',
    'Sec-Fetch-User': '?1',
    'Cache-Control': 'max-age=0',
}

session = requests.Session()
session.headers.update(headers)

إدارة الكوكيز

تقوم العديد من المواقع بتعيين الكوكيز للتتبع عند الزيارة الأولى وتتحقق من وجودها عند الطلبات اللاحقة. عدم وجود الكوكيز أو عدم تطابقها هو علامة على الروبوت.

import requests
import pickle

class SessionManager:
    def __init__(self, session_file='session.pkl'):
        self.session_file = session_file
        self.session = requests.Session()
        self.load_session()
        
    def load_session(self):
        """تحميل الجلسة المحفوظة"""
        try:
            with open(self.session_file, 'rb') as f:
                cookies = pickle.load(f)
                self.session.cookies.update(cookies)
        except FileNotFoundError:
            pass
            
    def save_session(self):
        """حفظ الكوكيز لإعادة الاستخدام"""
        with open(self.session_file, 'wb') as f:
            pickle.dump(self.session.cookies, f)
            
    def request(self, url, **kwargs):
        response = self.session.get(url, **kwargs)
        self.save_session()
        return response

# الاستخدام
manager = SessionManager('instagram_session.pkl')
response = manager.request('https://www.instagram.com/explore/')

مهم: عند تدوير الوكلاء، لا تنسَ إعادة تعيين الكوكيز إذا كانت مرتبطة بعنوان IP معين. عدم تطابق IP والكوكيز (مثل الكوكيز مع الموقع الجغرافي للولايات المتحدة وIP من ألمانيا) سيؤدي إلى الشكوك.

Referer وOrigin

تظهر رؤوس Referer وOrigin من أين جاء المستخدم. عدم وجودها أو القيم غير الصحيحة هي علامة حمراء.

# الترتيب الصحيح: الرئيسية → الفئة → المنتج
session = requests.Session()

# الخطوة 1: زيارة الصفحة الرئيسية
response = session.get('https://example.com/')

# الخطوة 2: الانتقال إلى الفئة
response = session.get(
    'https://example.com/category/electronics',
    headers={'Referer': 'https://example.com/'}
)

# الخطوة 3: عرض المنتج
response = session.get(
    'https://example.com/product/12345',
    headers={'Referer': 'https://example.com/category/electronics'}
)

محاكاة سلوك الإنسان

المعلمات التقنية هي نصف القضية فقط. تقوم أنظمة مكافحة الروبوتات الحديثة بتحليل أنماط السلوك: كيف يتفاعل المستخدم مع الصفحة، كم من الوقت يقضيه، كيف تتحرك الفأرة.

التمرير وحركة الفأرة

عند استخدام Selenium أو Puppeteer، أضف حركات عشوائية للفأرة وتمرير الصفحة:

from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
import random
import time

def human_like_mouse_move(driver):
    """حركة عشوائية للفأرة على الصفحة"""
    action = ActionChains(driver)
    
    for _ in range(random.randint(3, 7)):
        x = random.randint(0, 1000)
        y = random.randint(0, 800)
        action.move_by_offset(x, y)
        action.pause(random.uniform(0.1, 0.3))
    
    action.perform()

def human_like_scroll(driver):
    """محاكاة تمرير طبيعي"""
    total_height = driver.execute_script("return document.body.scrollHeight")
    current_position = 0
    
    while current_position < total_height:
        # خطوة تمرير عشوائية
        scroll_step = random.randint(100, 400)
        current_position += scroll_step
        
        driver.execute_script(f"window.scrollTo(0, {current_position});")
        
        # توقف مع تنوع
        time.sleep(random.uniform(0.5, 1.5))
        
        # أحيانًا نرجع قليلاً (كما يفعل الناس)
        if random.random() < 0.2:
            back_scroll = random.randint(50, 150)
            current_position -= back_scroll
            driver.execute_script(f"window.scrollTo(0, {current_position});")
            time.sleep(random.uniform(0.3, 0.8))

# الاستخدام
driver = webdriver.Chrome()
driver.get('https://example.com')

human_like_mouse_move(driver)
time.sleep(random.uniform(2, 4))
human_like_scroll(driver)

الوقت على الصفحة

يقضي المستخدمون الحقيقيون وقتًا على الصفحة: يقرؤون المحتوى، يتفحصون الصور. يتم التعرف بسهولة على الروبوت الذي ينتقل بين الروابط على الفور.

def realistic_page_view(driver, url, min_time=5, max_time=15):
    """
    عرض الصفحة بشكل واقعي مع النشاط
    """
    driver.get(url)
    
    # تأخير أولي (تحميل و"قراءة")
    time.sleep(random.uniform(2, 4))
    
    # تمرير
    human_like_scroll(driver)
    
    # نشاط إضافي
    total_time = random.uniform(min_time, max_time)
    elapsed = 0
    
    while elapsed < total_time:
        action_choice = random.choice(['scroll', 'mouse_move', 'pause'])
        
        if action_choice == 'scroll':
            # تمرير بسيط لأعلى/أسفل
            scroll_amount = random.randint(-200, 300)
            driver.execute_script(f"window.scrollBy(0, {scroll_amount});")
            pause = random.uniform(1, 3)
            
        elif action_choice == 'mouse_move':
            human_like_mouse_move(driver)
            pause = random.uniform(0.5, 2)
            
        else:  # pause
            pause = random.uniform(2, 5)
        
        time.sleep(pause)
        elapsed += pause

أنماط التنقل

تجنب الأنماط المشبوهة: الانتقال المباشر إلى صفحات عميقة، تجاهل الصفحة الرئيسية، التجول المتسلسل لجميع العناصر دون تخطي.

الممارسات الجيدة:

  • ابدأ من الصفحة الرئيسية أو الأقسام الشائعة
  • استخدم التنقل الداخلي للموقع بدلاً من URL المباشر
  • أحيانًا ارجع للخلف أو انتقل إلى أقسام أخرى
  • تنوع عمق العرض: لا تصل دائمًا إلى النهاية
  • أضف "أخطاء": الانتقال إلى روابط غير موجودة، العودة

تجاوز Cloudflare وDataDome وغيرها من الحمايات

تتطلب أنظمة مكافحة الروبوتات المتخصصة نهجًا شاملاً. تستخدم تحديات JavaScript، CAPTCHA، وتحليل السلوك في الوقت الحقيقي.

Cloudflare

تستخدم Cloudflare عدة مستويات من الحماية: فحص سلامة المتصفح، تحدي JavaScript، CAPTCHA. لتجاوز الحماية الأساسية، يكفي وجود بصمة TLS صحيحة وتنفيذ JavaScript:

# الخيار 1: cloudscraper (حل تلقائي لتحديات JS)
import cloudscraper

scraper = cloudscraper.create_scraper(
    browser={
        'browser': 'chrome',
        'platform': 'windows',
        'desktop': True
    }
)

response = scraper.get('https://protected-site.com')

# الخيار 2: undetected-chromedriver (لحالات معقدة)
import undetected_chromedriver as uc

options = uc.ChromeOptions()
options.add_argument('--proxy-server=http://proxy:port')

driver = uc.Chrome(options=options)
driver.get('https://protected-site.com')

# الانتظار حتى يتم تجاوز التحدي
time.sleep(5)

# الحصول على الكوكيز لـ requests
cookies = driver.get_cookies()
session = requests.Session()
for cookie in cookies:
    session.cookies.set(cookie['name'], cookie['value'])

DataDome

يقوم DataDome بتحليل سلوك المستخدم في الوقت الحقيقي: حركات الفأرة، أسلوب الكتابة، التوقيتات. لتجاوز ذلك، تحتاج إلى متصفح كامل مع محاكاة للنشاط:

from playwright.sync_api import sync_playwright
import random

def bypass_datadome(url, proxy=None):
    with sync_playwright() as p:
        browser = p.chromium.launch(
            headless=False,  # يقوم DataDome بالكشف عن الوضع بدون رأس
            proxy={'server': proxy} if proxy else None
        )
        
        context = browser.new_context(
            viewport={'width': 1920, 'height': 1080},
            user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64)...'
        )
        
        page = context.new_page()
        
        # حقن السكربتات لإخفاء الأتمتة
        page.add_init_script("""
            Object.defineProperty(navigator, 'webdriver', {get: () => false});
            window.chrome = {runtime: {}};
        """)
        
        page.goto(url)
        
        # محاكاة سلوك الإنسان
        time.sleep(random.uniform(2, 4))
        
        # حركات عشوائية للفأرة
        for _ in range(random.randint(5, 10)):
            page.mouse.move(
                random.randint(100, 1800),
                random.randint(100, 1000)
            )
            time.sleep(random.uniform(0.1, 0.3))
        
        # تمرير
        page.evaluate(f"window.scrollTo(0, {random.randint(300, 800)})")
        time.sleep(random.uniform(1, 2))
        
        content = page.content()
        browser.close()
        
        return content

CAPTCHA

لحل CAPTCHA تلقائيًا، استخدم خدمات التعرف (2captcha، Anti-Captcha) أو استراتيجيات التجنب:

  • قلل من تكرار الطلبات إلى مستوى لا يسبب CAPTCHA
  • استخدم IP سكني نظيف ذو سمعة جيدة
  • اعمل من خلال حسابات مصرح بها (لديها عتبة CAPTCHA أعلى)
  • وزع الحمل على الوقت (تجنب ساعات الذروة)

المراقبة ومعالجة الحظر

حتى مع أفضل الممارسات، فإن الحظر لا مفر منه. من المهم اكتشافها بسرعة ومعالجتها بشكل صحيح.

مؤشرات الحظر

الإشارة الوصف الإجراء
HTTP 429 طلبات كثيرة جدًا زيادة التأخيرات، تغيير IP
HTTP 403 ممنوع (حظر IP) تغيير الوكيل، تحقق من بصمة التقنية
CAPTCHA يتطلب التحقق حلها أو تقليل النشاط
استجابة فارغة المحتوى لا يتم تحميله تحقق من JavaScript، الكوكيز
إعادة توجيه إلى /blocked حظر واضح تغيير الاستراتيجية بالكامل

نظام المحاولات المتكررة

import requests
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry

def create_session_with_retries():
    """
    جلسة مع محاولات تلقائية ومعالجة الأخطاء
    """
    session = requests.Session()
    
    retry_strategy = Retry(
        total=5,
        backoff_factor=2,  # 2، 4، 8، 16، 32 ثانية
        status_forcelist=[429, 500, 502, 503, 504],
        method_whitelist=["GET", "POST"]
    )
    
    adapter = HTTPAdapter(max_retries=retry_strategy)
    session.mount("http://", adapter)
    session.mount("https://", adapter)
    
    return session

def safe_request(url, session, max_attempts=3):
    """
    طلب مع معالجة الحظر
    """
    for attempt in range(max_attempts):
        try:
            response = session.get(url, timeout=15)
            
            # تحقق من الحظر
            if response.status_code == 403:
                print(f"تم حظر IP. تدوير الوكيل...")
                # منطق تغيير الوكيل
                continue
                
            elif response.status_code == 429:
                wait_time = int(response.headers.get('Retry-After', 60))
                print(f"تم تحديد المعدل. الانتظار {wait_time} ثواني...")
                time.sleep(wait_time)
                continue
                
            elif 'captcha' in response.text.lower():
                print("تم اكتشاف CAPTCHA")
                # منطق حل CAPTCHA أو التجاوز
                return None
                
            return response
            
        except requests.exceptions.Timeout:
            print(f"انتهت المهلة في المحاولة {attempt + 1}")
            time.sleep(5 * (attempt + 1))
            
        except requests.exceptions.ProxyError:
            print("خطأ في الوكيل. تدوير...")
            # تغيير الوكيل
            continue
            
    return None

التسجيل والتحليل

تتبع المقاييس لتحسين الاستراتيجية:

import logging
from collections import defaultdict
from datetime import datetime

class ScraperMetrics:
    def __init__(self):
        self.stats = {
            'total_requests': 0,
            'successful': 0,
            'rate_limited': 0,
            'blocked': 0,
            'captcha': 0,
            'errors': 0,
            'proxy_failures': defaultdict(int)
        }
        
    def log_request(self, status, proxy=None):
        self.stats['total_requests'] += 1
        
        if status == 200:
            self.stats['successful'] += 1
        elif status == 429:
            self.stats['rate_limited'] += 1
        elif status == 403:
            self.stats['blocked'] += 1
            if proxy:
                self.stats['proxy_failures'][proxy] += 1
                
    def get_success_rate(self):
        if self.stats['total_requests'] == 0:
            return 0
        return (self.stats['successful'] / self.stats['total_requests']) * 100
        
    def print_report(self):
        print(f"\n=== تقرير الزحف ===")
        print(f"إجمالي الطلبات: {self.stats['total_requests']}")
        print(f"نسبة النجاح: {self.get_success_rate():.2f}%")
        print(f"تم تحديد المعدل: {self.stats['rate_limited']}")
        print(f"محظور: {self.stats['blocked']}")
        print(f"CAPTCHA: {self.stats['captcha']}")
        
        if self.stats['proxy_failures']:
            print(f"\nالوكلاء المشكلين:")
            for proxy, count in sorted(
                self.stats['proxy_failures'].items(), 
                key=lambda x: x[1], 
                reverse=True
            )[:5]:
                print(f"  {proxy}: {count} فشل")

# الاستخدام
metrics = ScraperMetrics()

for url in urls:
    response = safe_request(url, session)
    if response:
        metrics.log_request(response.status_code, current_proxy)
    
metrics.print_report()

المؤشرات المثلى: نسبة النجاح فوق 95% - نتيجة ممتازة. 80-95% - مقبولة، لكن هناك ما يمكن تحسينه. أقل من 80% - راجع الاستراتيجية: ربما يكون تحديد المعدل عدوانيًا جدًا، أو الوكلاء سيئين، أو مشاكل في بصمة التقنية.

الخاتمة

الحماية من الحظر تتطلب فهمًا عميقًا لآليات اكتشاف الأتمتة وتطبيق استراتيجيات فعالة لتجاوزها. باستخدام التقنيات والأدوات الصحيحة، يمكنك تقليل مخاطر الحظر وتحسين فعالية عمليات الزحف والأتمتة الخاصة بك.

```