Skip to content
مقاله / 2 دقیقه مطالعه

پروکسی‌های چرخشی برای وب‌اسکرپینگ: requests پایتون، میدل‌ور Scrapy و رهگیری رتبه

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

اگر چند صد صفحه را از یک IP اسکرپ کنید، دیر یا زود به محدودیت نرخ، یک CAPTCHA یا یک بلاک نرم برمی‌خورید. چرخش راه‌حل استاندارد است — اما چرخش بد از نبودش بدتر است: بودجهٔ پروکسی را می‌سوزاند، اشکال‌زدایی را سخت‌تر می‌کند و می‌تواند حتی بیشتر از یک خزندهٔ پیوسته و مؤدب شبیه ربات به نظر برسد.

این راهنما پوشش می‌دهد که چرخش چگونه کار می‌کند، چگونه آن را در پایتون با requests و در Scrapy با یک میدل‌ور دانلودر پیاده‌سازی کنیم، و چگونه همان تکنیک‌ها در رهگیری رتبهٔ SERP به کار می‌آیند.

پیش از چرخش، بررسی کنید که آیا مشکل خودِ چرخش است

چرخش بلاک‌های سطح IP را پنهان می‌کند. اما این موارد را برطرف نمی‌کند:

  • مشکل الگو. هیچ تعداد IP نمی‌تواند خزنده‌ای را نجات دهد که پنجاه بار در ثانیه همان URL را با user agent پیش‌فرض درخواست می‌کند.
  • مشکل نشست. اگر جریان کار شما نیازمند باقی‌ماندن در حالت ورود است، یک IP جدید در میانهٔ نشست شبیه سرقت حساب به نظر می‌رسد.
  • مشکل جغرافیایی. اگر محتوایی که نیاز دارید محدود به منطقه است، به کشور درست نیاز دارید، نه IP بیشتر.

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

نوع پروکسی متناسب با کار را انتخاب کنید

نوع نقطه قوت معمول مراقب چه باشید
دیتاسنتر سریع، همزمانی بالا، به‌راحتی در دسترس به‌راحتی شناسایی می‌شود؛ توسط سایت‌های سختگیر بلاک می‌شود
مسکونی با ترافیک کاربران واقعی مخلوط می‌شود کندتر؛ محدودیت پهنای باند؛ مدیریت نشست مهم است
موبایل اعتماد بالا، سخت‌ترین برای بلاک کردن گران؛ ناپایدار؛ نشست‌های همزمان کمتر
ISP / مسکونی استاتیک IP پایدار و یکنواخت استخرهای کوچک‌تر؛ چرخش کمتر

برای داده‌های ساخت‌یافته روی سایت‌های آسان‌گیر، دیتاسنتر معمولاً کافی است. برای نتایج جستجو، بازارگاه‌ها و سایت‌های سفر، معمولاً پروکسی مسکونی یا موبایل لازم است. ارائه‌دهندگان را بر اساس دانه‌بندی چرخش، کنترل نشست، پوشش جغرافیایی و نحوهٔ برخورد با بلاک‌ها ارزیابی کنید — نه بر اساس یک عدد چشمگیر در تیتر تعداد IP.

راهبردهای چرخش

چرخش به‌ازای هر درخواست

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

نشست‌های چسبنده

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

چسبندگی جغرافیایی

برای رهگیری رتبه و بررسی قیمت‌ها معمولاً می‌خواهید در سراسر یک مجموعهٔ پرس‌وجو همان شهر یا کشور را داشته باشید، زیرا نتایج بر اساس موقعیت مکانی تغییر می‌کنند. درون یک محدودهٔ جغرافیایی بچرخانید، نه بین محدوده‌های جغرافیایی مختلف.

محدودسازی همزمانی

چرخش و محدودسازی نرخ مکمل یکدیگرند، نه جانشین هم. خزنده‌ای با پنج درخواست همزمان که Retry-After را رعایت می‌کند، از خزنده‌ای با دویست ترد که آن‌قدر هر IP را می‌کوبد تا بلاک شود، بهتر عمل می‌کند.

پایتون: چرخش پروکسی با requests

اگر به پشتیبانی SOCKS نیاز دارید آن را نصب کنید. کتابخانهٔ requests در زیر پوسته از PySocks استفاده می‌کند:

pip install "requests[socks]"

سپس در یک استخر بچرخانید:

import itertools
import requests

POOL = [
    'http://user:[email protected]:8000',
    'http://user:[email protected]:8000',
    'socks5h://user:[email protected]:1080',
]

proxy_cycle = itertools.cycle(POOL)

def fetch(url, timeout=20):
    proxy = next(proxy_cycle)
    proxies = {'http': proxy, 'https': proxy}
    response = requests.get(url, proxies=proxies, timeout=timeout)
    response.raise_for_status()
    return response.text

چند نکته که ارزش افزودن در محیط عملیاتی را دارد:

  • روی 429 یا 403 با یک پروکسی متفاوت دوباره تلاش کنید، نه همان یکی.
  • برای استفادهٔ مجدد از اتصال از requests.Session() استفاده کنید، اما به‌جای یک نشست برای کل خزش، برای هر IP یک نشست بسازید.
  • ثبت کنید کدام پروکسی کدام نتیجه را تولید کرده تا بتوانید IPهای بد را حذف کنید نه اینکه دوباره قرعه‌کشی کنید.
  • وقتی می‌خواهید نام‌های میزبان در پروکسی resolve شوند و نه به‌صورت محلی، از socks5h:// (به h دقت کنید) استفاده کنید.

Scrapy: یک میدل‌ور دانلودر پروکسی چرخشی

Scrapy پیش‌تر احراز هویت پروکسی را از طریق میدل‌ور پروکسی HTTP داخلی خود مدیریت می‌کند، پس فقط باید request.meta['proxy'] را پیش از ارسال درخواست تنظیم کنید. یک میدل‌ور چرخش ساده چنین است:

import random

class RotatingProxyMiddleware:
    def __init__(self, proxies):
        self.proxies = proxies

    @classmethod
    def from_crawler(cls, crawler):
        proxies = crawler.settings.getlist('ROTATING_PROXIES')
        if not proxies:
            raise ValueError('ROTATING_PROXIES is empty')
        return cls(proxies)

    def process_request(self, request, spider):
        request.meta['proxy'] = random.choice(self.proxies)

آن را در ماژول تنظیمات خود ثبت کنید:

DOWNLOADER_MIDDLEWARES = {
    'myproject.middlewares.RotatingProxyMiddleware': 350,
}

ROTATING_PROXIES = [
    'http://user:[email protected]:8000',
    'http://user:[email protected]:8000',
]

AUTOTHROTTLE_ENABLED = True
RETRY_HTTP_CODES = [403, 429, 500, 502, 503, 504]

دو نکته:

  • یک random.choice ساده‌لوحانه مدام از IPهای بلاک‌شده دوباره استفاده می‌کند. پروژه‌های اجتماعی مانند scrapy-rotating-proxies تشخیص بلاک و آمار به‌ازای هر پروکسی را روی همان ایده اضافه می‌کنند، که وقتی از چند درخواست فراتر می‌روید ارزش این وابستگی را دارد.
  • میدل‌ور retry در Scrapy معمولاً با همان پروکسی دوباره تلاش می‌کند. اگر بلاک شدن مشکل شماست، کاری کنید که مسیر تلاش مجدد انتخاب پروکسی را دوباره اجرا کند.

به‌کارگیری همین رویکرد در رهگیری رتبه

رهگیرهای رتبه یک نیاز پروکسی دارند که خزنده‌های عمومی ندارند: یکسانی موقعیت مکانی. کلیدواژه‌ای که یک بار از یک شهر و بار بعد از شهر دیگری بررسی شود، SERPهای متفاوت و یک نمودار جابه‌جایی بی‌معنا تولید می‌کند.

قواعد عملی برای رهگیری رتبه:

  • برای هر کلیدواژهٔ رهگیری‌شده یک موقعیت انتخاب کنید و آن را در بین اجراها ثابت نگه دارید.
  • IP را به‌طور دوره‌ای تازه کنید تا علامت‌گذاری نشوید، اما در همان شهر یا منطقه بمانید.
  • هنگام رهگیری نتایج موبایل از پروکسی‌های موبایل استفاده کنید، چون SERP دسکتاپ و موبایل به‌قدری متفاوت‌اند که مهم است.
  • تهاجمی کش کنید و به‌جای پیوسته، بر اساس زمان‌بندی بررسی کنید.

همچنین ارزش دارد صریح گفته شود: اسکرپ کردن موتورهای جستجو معمولاً شرایط استفادهٔ آن‌ها را نقض می‌کند. اگر به داده‌های رتبهٔ قابل اتکا نیاز دارید، APIهای رسمی و فیدهای مجاز رهگیری رتبه مسیر کم‌ریسک‌تر هستند. پروکسی‌ها برای مواردی هستند که واقعاً API وجود ندارد.

چگونه بفهمیم چرخش کار می‌کند

این موارد را در کل یک خزش دنبال کنید، نه به‌ازای هر درخواست:

  • نرخ موفقیت به‌ازای هر پروکسی، یعنی پاسخ‌های 2xx تقسیم بر تعداد تلاش‌ها.
  • نرخ بلاک به‌ازای هر پروکسی، همراه با ثبت نوع بلاک: 403، CAPTCHA، بدنهٔ خالی، صفحهٔ رضایت.
  • میانهٔ زمان پاسخ به‌ازای هر پروکسی. پروکسی‌ای که کار می‌کند اما سی ثانیه برای هر صفحه طول می‌کشد، ضرر خالص است.
  • IPهای یکتایی که واقعاً استفاده شده‌اند، در مقابل اندازهٔ استخری که پیکربندی کرده‌اید.

اگر نرخ موفقیت در همهٔ IPها یکسان است، مشکل شما اعتبار IP نیست و هیچ مقدار چرخشی کمکی نخواهد کرد.

جمع‌بندی

فقط پس از آنکه نرخ درخواست، هدرها و منطق نشست را اصلاح کردید، بچرخانید. برای واکشی‌های بی‌حالت از چرخش به‌ازای هر درخواست و برای هر چیز چندمرحله‌ای از نشست‌های چسبنده استفاده کنید. در پایتون، requests به افزونهٔ SOCKS و یک پروکسی به‌ازای هر نشست نیاز دارد، در حالی که در Scrapy یک میدل‌ور دانلودر که request.meta['proxy'] را تخصیص می‌دهد بیشتر راه را طی می‌کند و بسته‌های ردیابی بلاک بقیه را انجام می‌دهند. و برای رهگیری رتبه، جغرافیا را الزام و چرخش را نگهداری در نظر بگیرید.