بازگشت به وبلاگ

چگونه از مسدود شدن در درخواست‌های انبوه جلوگیری کنیم

مکانیسم‌های شناسایی اتوماسیون و تکنیک‌های خاص حفاظت در برابر مسدودسازی در درخواست‌های انبوه را بررسی می‌کنیم: از چرخش پایه پروکسی تا شبیه‌سازی رفتار انسانی.

📅۳۰ آذر ۱۴۰۴
```html

محافظت در برابر مسدود شدن در درخواست‌های انبوه: تکنیک‌ها و ابزارها

مسدود شدن حساب‌ها و آدرس‌های IP — مشکل اصلی در پارس کردن، اتوماسیون و عملیات انبوه در شبکه‌های اجتماعی است. سیستم‌های ضد ربات مدرن ده‌ها پارامتر را تجزیه و تحلیل می‌کنند: از فرکانس درخواست‌ها تا اثر انگشت مرورگر. در این راهنما، مکانیزم‌های خاص شناسایی اتوماسیون و روش‌های عملی دور زدن آن‌ها را بررسی خواهیم کرد.

مکانیزم‌های شناسایی اتوماسیون

سیستم‌های محافظتی مدرن از تجزیه و تحلیل چند سطحی برای شناسایی ربات‌ها استفاده می‌کنند. درک این مکانیزم‌ها برای انتخاب استراتژی مناسب دور زدن حیاتی است.

پارامترهای اصلی تجزیه و تحلیل

شهرت IP: سیستم‌های ضد ربات تاریخچه آدرس IP، تعلق آن به دیتاسنترها و وجود در لیست‌های سیاه را بررسی می‌کنند. IPهای معروف از پروکسی‌ها بیشتر مسدود می‌شوند.

فرکانس درخواست‌ها (Request Rate): انسان به‌طور فیزیکی نمی‌تواند 100 درخواست در دقیقه ارسال کند. سیستم‌ها نه تنها تعداد کل، بلکه توزیع زمانی را نیز تجزیه و تحلیل می‌کنند — فواصل یکنواخت بین درخواست‌ها ربات را فاش می‌کند.

الگوهای رفتاری: توالی اقدامات، عمق اسکرول، حرکات ماوس، زمان در صفحه. رباتی که به‌طور فوری به لینک‌ها بدون تأخیر می‌رود، به راحتی شناسایی می‌شود.

اثر انگشت‌های فنی: User-Agent، هدرهای HTTP، ترتیب هدرها، اثر انگشت TLS، اثر انگشت Canvas/WebGL. عدم تطابق در این پارامترها — پرچم قرمز برای سیستم‌های ضد ربات است.

پارامتر چه چیزی تجزیه و تحلیل می‌شود ریسک شناسایی
آدرس IP شهرت، ASN، موقعیت جغرافیایی بالا
User-Agent نسخه مرورگر، سیستم‌عامل، دستگاه متوسط
اثر انگشت TLS مجموعه رمزها، گسترش‌ها بالا
اثر انگشت HTTP/2 ترتیب هدرها، تنظیمات بالا
Canvas/WebGL رندر گرافیک متوسط
رفتار کلیک‌ها، اسکرول، زمان بالا

محدودیت نرخ و کنترل فرکانس درخواست‌ها

کنترل سرعت ارسال درخواست‌ها — اولین خط دفاع در برابر مسدود شدن است. حتی با چرخش پروکسی، پارس کردن بسیار تهاجمی منجر به مسدود شدن می‌شود.

تأخیرهای دینامیک

فواصل ثابت (مثلاً دقیقاً 2 ثانیه بین درخواست‌ها) به راحتی شناسایی می‌شوند. از تأخیرهای تصادفی با توزیع نرمال استفاده کنید:

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}s")

# کاربرد
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، درایورها و سیستم‌عامل رندر می‌کنند. سایت‌ها از این برای ایجاد اثر انگشت منحصر به فرد دستگاه استفاده می‌کنند. هنگام استفاده از مرورگرهای headless (Selenium، Puppeteer) مهم است که نشانه‌های اتوماسیون را پنهان کنید:

// Puppeteer: پنهان‌سازی حالت headless
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 حالت headless را شناسایی می‌کند
            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}s...")
                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% — استراتژی خود را بررسی کنید: ممکن است محدودیت نرخ خیلی تهاجمی باشد، پروکسی‌های بد یا مشکلات اثر انگشت‌گذاری وجود داشته باشد.

نتیجه‌گیری

محافظت در برابر مسدود شدن در درخواست‌های انبوه نیاز به استراتژی‌های دقیق و پیوسته دارد. با استفاده از تکنیک‌های ذکر شده در این مقاله، می‌توانید خطر مسدود شدن را به حداقل برسانید و از موفقیت بیشتری در عملیات خود برخوردار شوید.

```