Skip to content
Advanced / 3 min read

چرخش پراکسی در Scrapy: چگونه پراکسی‌ها را در Scrapy بچرخانیم (و چه زمانی یک دروازه اختصاصی WireGuard بهتر است)

چرخش پراکسی را در Scrapy با میدل‌ور سفارشی پیاده‌سازی کنید، مسدودسازی‌ها را به‌صورت روان مدیریت کنید، و بیاموزید چه زمانی یک دروازه پایدار WireGuard مانند NordLayer انتخاب درستی برای پایش سئو و وب‌اسکرپینگ است.

لینوکس WireGuard وب اسکرپینگ پایش سئو

مرور کلی

وب‌اسکرپینگ در مقیاس بزرگ اغلب به محدودیت نرخ، مسدودسازی IP یا محدودیت‌های جغرافیایی برمی‌خورد. Scrapy، یک فریم‌ورک محبوب پایتون، به‌صورت پیش‌فرض پراکسی‌ها را نمی‌چرخاند. این آموزش نشان می‌دهد چگونه یک میدل‌ور پراکسی چرخشی برای Scrapy بسازید، تلاش‌های مجدد را پیکربندی کنید، و تصمیم بگیرید چه زمانی یک دروازه اختصاصی VPN WireGuard (مانند NordLayer) گزینه مناسب‌تری از یک استخر پراکسی چرخشی است.

دو رویکرد را یاد خواهید گرفت:

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

NordLayer تونل‌های WireGuard در سطح تجاری با دروازه‌های اختصاصی و صورتحساب ماهانه ثابت ارائه می‌دهد. این یک سرویس پراکسی چرخشی نیست، اما می‌تواند به‌عنوان IP خروجی پایدار برای اسپایدرهای Scrapy شما زمانی که یکنواختی مهم است، عمل کند.

پیش‌نیازها

  • پایتون 3.7 یا جدیدتر
  • آشنایی پایه با Scrapy
  • فهرستی از پراکسی‌های HTTP/HTTPS یا SOCKS5 (برای رویکرد چرخشی)
  • اختیاری: یک حساب NordLayer با دروازه اختصاصی WireGuard (برای رویکرد IP پایدار)
  • یک سرور لینوکس یا ماشین محلی (دستورها برای Debian/Ubuntu نشان داده شده‌اند؛ برای سایر سیستم‌ها تطبیق دهید)

درک چرخش پراکسی در Scrapy

Scrapy از میدل‌ورهای دانلودر برای پردازش درخواست‌ها و پاسخ‌ها استفاده می‌کند. برای چرخش پراکسی‌ها، هر درخواست را رهگیری می‌کنید، یک پراکسی از یک استخر اختصاص می‌دهید، و به‌صورت اختیاری هنگامی که درخواستی شکست می‌خورد با پراکسی جدید دوباره تلاش می‌کنید.

مفاهیم کلیدی:

  • استخر پراکسی: فهرستی از URLهای پراکسی (در صورت نیاز همراه با اعتبارنامه).
  • راهبرد چرخش: انتخاب تصادفی، نوبتی (round-robin)، یا وزن‌دهی بر اساس سلامت پراکسی.
  • منطق تلاش مجدد: بازگرداندن درخواست‌های ناموفق به صف با پراکسی متفاوت.

چه زمانی به‌جای آن دروازه اختصاصی WireGuard را در نظر بگیریم:

  • برای ردیابی رتبه سئو در چندین مکان به IP یکنواخت نیاز دارید.
  • سایت هدف شما تغییرات مکرر IP را شدیدتر از IPهای ثابت مسدود می‌کند.
  • دسترسی رمزنگاری‌شده و مدیریت‌شده تیمی می‌خواهید بدون نگهداری فهرست پراکسی.

مراحل

۱. نصب Scrapy و ساخت یک پروژه

اگر هنوز انجام نداده‌اید، Scrapy را نصب کنید و پروژه جدیدی بسازید.

pip install scrapy
scrapy startproject proxy_scraper
cd proxy_scraper
scrapy genspider example example.com

۲. ساخت میدل‌ور پراکسی چرخشی

فایل proxy_scraper/middlewares.py را باز کنید و میدل‌ور زیر را اضافه کنید. این میدل‌ور برای هر درخواست یک پراکسی تصادفی انتخاب می‌کند و در کدهای وضعیت رایج مسدودسازی دوباره تلاش می‌کند.

# proxy_scraper/middlewares.py
import random
from scrapy import signals
from scrapy.exceptions import NotConfigured

class RotatingProxyMiddleware:
    def __init__(self, proxy_list):
        self.proxy_list = proxy_list
        self.current_proxy = None

    @classmethod
    def from_crawler(cls, crawler):
        proxy_list = crawler.settings.getlist('ROTATING_PROXY_LIST')
        if not proxy_list:
            raise NotConfigured('ROTATING_PROXY_LIST is empty')
        return cls(proxy_list)

    def process_request(self, request, spider):
        self.current_proxy = random.choice(self.proxy_list)
        request.meta['proxy'] = self.current_proxy
        spider.logger.debug(f'Using proxy: {self.current_proxy}')

    def process_response(self, request, response, spider):
        if response.status in [403, 429]:
            spider.logger.warning(f'Blocked with proxy {self.current_proxy}. Retrying...')
            new_request = request.copy()
            new_request.dont_filter = True
            return new_request
        return response

۳. پیکربندی تنظیمات برای فعال‌سازی میدل‌ور و تعریف پراکسی‌ها

فایل proxy_scraper/settings.py را ویرایش کنید تا میدل‌ور فعال شود و فهرست پراکسی‌های خود را ارائه دهید. پراکسی‌های نمونه را با پراکسی‌های خودتان جایگزین کنید.

# proxy_scraper/settings.py

DOWNLOADER_MIDDLEWARES = {
    'proxy_scraper.middlewares.RotatingProxyMiddleware': 543,
}

ROTATING_PROXY_LIST = [
    'http://user:[email protected]:8080',
    'http://user:[email protected]:8080',
    'socks5://user:[email protected]:1080',
]

# Optional: retry settings
RETRY_TIMES = 5
RETRY_HTTP_CODES = [500, 502, 503, 504, 522, 524, 408, 429, 403]

۴. آزمایش چرخش با یک اسپایدر ساده

اسپایدر خود را اجرا کنید و لاگ‌های DEBUG را تماشا کنید تا تأیید کنید پراکسی‌های متفاوتی استفاده می‌شوند.

scrapy crawl example -L DEBUG

اگر خطوطی مانند Using proxy: http://... می‌بینید، میدل‌ور درست کار می‌کند. اگر همه درخواست‌ها از پراکسی یکسانی استفاده می‌کنند، ترتیب میدل‌ور و خالی نبودن ROTATING_PROXY_LIST را بررسی کنید.

۵. بهبود پایایی با بررسی سلامت و عقب‌نشینی (backoff)

برای اسکرپینگ تولیدی، ردیابی پایه سلامت پراکسی را اضافه کنید. این نمونه پس از مسدودسازی‌های مکرر یک پراکسی را ناموفق علامت می‌زند و آن را موقتاً حذف می‌کند.

# proxy_scraper/middlewares.py (enhanced)
import random
from collections import defaultdict

class RotatingProxyMiddleware:
    def __init__(self, proxy_list):
        self.proxy_list = proxy_list
        self.failure_count = defaultdict(int)
        self.max_failures = 3

    @classmethod
    def from_crawler(cls, crawler):
        proxy_list = crawler.settings.getlist('ROTATING_PROXY_LIST')
        return cls(proxy_list)

    def process_request(self, request, spider):
        available = [p for p in self.proxy_list if self.failure_count[p] < self.max_failures]
        if not available:
            spider.logger.error('All proxies exhausted')
            return
        proxy = random.choice(available)
        request.meta['proxy'] = proxy

    def process_response(self, request, response, spider):
        proxy = request.meta.get('proxy')
        if response.status in [403, 429]:
            self.failure_count[proxy] += 1
            new_request = request.copy()
            new_request.dont_filter = True
            return new_request
        else:
            self.failure_count[proxy] = 0
        return response

۶. چه زمانی به دروازه اختصاصی WireGuard سوییچ کنیم

پراکسی‌های چرخشی برای اسکرپینگ بی‌حالت و در مقیاس بزرگ عالی هستند. اما برخی کارها به یک IP پایدار و اختصاصی نیاز دارند:

  • ردیابی رتبه سئو که در آن به داده‌های مکانی یکنواخت نیاز دارید
  • دسترسی به APIهایی که نشست‌ها را به یک IP گره می‌زنند
  • اسکرپینگ تیمی که در آن چند کاربر از همان IP خروجی مشترک استفاده می‌کنند

تونل‌های WireGuard شرکت NordLayer یک دروازه اختصاصی با صورتحساب ماهانه ثابت به شما می‌دهند. می‌توانید تمام ترافیک Scrapy را از طریق تونل مسیردهی کنید و عملاً از یک IP ثابت واحد استفاده کنید.

۷. راه‌اندازی WireGuard روی لینوکس و مسیردهی Scrapy از طریق آن

WireGuard را نصب کنید و یک تونل با استفاده از اعتبارنامه‌های دروازه NordLayer خود پیکربندی کنید.

sudo apt update
sudo apt install wireguard

یک فایل پیکربندی در /etc/wireguard/wg0.conf بسازید (جانگهدارها را با مقادیر NordLayer خود جایگزین کنید).

[Interface]
PrivateKey = <your-private-key>
Address = 10.0.0.2/32
DNS = 1.1.1.1

[Peer]
PublicKey = <nordlayer-public-key>
Endpoint = <gateway-ip>:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25

تونل را بالا بیاورید:

sudo wg-quick up wg0

اکنون تمام ترافیک Scrapy (و هر ترافیک دیگر) از طریق دروازه NordLayer خارج می‌شود. بررسی کنید که IP عمومی شما تغییر کرده است:

curl ifconfig.me

اسپایدر Scrapy خود را طبق معمول اجرا کنید. از IP پایدار دروازه استفاده خواهد کرد.

۸. ترکیب رویکردها برای اسکرپینگ هیبریدی

می‌توانید از هر دو استفاده کنید: بیشتر درخواست‌ها را از طریق پراکسی‌های چرخشی مسیردهی کنید، اما درخواست‌هایی که به IP یکنواخت نیاز دارند را از طریق تونل WireGuard بفرستید. در Scrapy، می‌توانید برای درخواست‌های خاص، پراکسی را به‌صورت شرطی روی None تنظیم کنید (که از مسیر پیش‌فرض سیستم، یعنی تونل WireGuard، استفاده می‌کند).

# Example: in a spider, for rank-tracking requests, don't set a proxy
# The default route (WireGuard) will be used.
def start_requests(self):
    # Rotating proxies for general pages
    yield scrapy.Request('https://example.com/general', meta={'proxy': None})
    # For rank tracking, bypass the rotating middleware
    yield scrapy.Request('https://example.com/serp', meta={'proxy': 'direct'})

سپس میدل‌ور را تغییر دهید تا وقتی proxy == 'direct' است از چرخش صرف‌نظر کند:

def process_request(self, request, spider):
    if request.meta.get('proxy') == 'direct':
        return None  # use default route
    # ... rest of rotation logic

عیب‌یابی

  • میدل‌ور اعمال نمی‌شود: مطمئن شوید DOWNLOADER_MIDDLEWARES مسیر درست را شامل می‌شود و مقدار آن (543) با میدل‌ورهای دیگر تعارض ندارد. ترتیب میدل‌ورهای پیش‌فرض Scrapy را بررسی کنید.
  • همه درخواست‌ها هنوز از همان IP استفاده می‌کنند: بررسی کنید که ROTATING_PROXY_LIST پر شده باشد و process_request میدل‌ور در حال اجراست. یک print یا لاگ اشکال‌زدایی اضافه کنید.
  • خطاهای مکرر 403/429: ممکن است پراکسی‌های شما مسدود یا بیش از حد کند باشند. CONCURRENT_REQUESTS و DOWNLOAD_DELAY را کاهش دهید، یا به پراکسی‌های باکیفیت‌تر سوییچ کنید. اگر سایت هدف IPهای چرخشی را شدیداً مسدود می‌کند، یک دروازه اختصاصی WireGuard را در نظر بگیرید.
  • تونل WireGuard متصل نمی‌شود: کلید خصوصی، کلید عمومی، endpoint و قواعد فایروال (به‌طور پیش‌فرض پورت UDP 51820) را دوباره بررسی کنید. برای دیدن وضعیت handshake دستور sudo wg show را اجرا کنید.
  • Scrapy تونل WireGuard را نادیده می‌گیرد: اگر AllowedIPs = 0.0.0.0/0 را تنظیم کرده‌اید، همه ترافیک باید از تونل مسیردهی شود. با ip route تأیید کنید و با curl ifconfig.me آزمایش کنید.

خلاصه

اکنون می‌دانید چگونه چرخش پراکسی را در Scrapy با میدل‌ور سفارشی پیاده‌سازی کنید، منطق تلاش مجدد اضافه کنید، و سلامت پراکسی را پایش کنید. برای پروژه‌هایی که به یک IP پایدار و اختصاصی نیاز دارند—مانند ردیابی رتبه سئو یا دسترسی تیمی—یک دروازه WireGuard مانند NordLayer می‌تواند مکمل یا جایگزین پراکسی‌های چرخشی باشد. رویکردی را انتخاب کنید که با اهداف اسکرپینگ شما همخوانی دارد: چرخش برای مقیاس و ناشناسی، دروازه‌های اختصاصی برای یکنواختی و کنترل.