چگونه از پروکسیهای مسکونی و دیتاسنتری Smartproxy با Scrapy در لینوکس استفاده کنیم
یک میانافزار دانلودر Scrapy بسازید که پروکسیهای HTTP مسکونی و دیتاسنتری Smartproxy را در لینوکس میچرخاند، با اعتبارنامههای مبتنی بر محیط و تلاشهای مجدد پشتیبان بین استخرها.
مرور کلی
HttpProxyMiddleware داخلی Scrapy میتواند یک درخواست را از طریق یک پروکسی HTTP مسیریابی کند، اما خزش تولیدی با Smartproxy معمولاً به دو چیز نیاز دارد: یک استخر مسکونی برای درخواستهای هدفگیری جغرافیایی یا مقاوم در برابر مسدودسازی، و یک استخر دیتاسنتری برای درخواستهای پرحجم. این آموزش نشان میدهد چگونه یک میانافزار دانلودر سفارشی اضافه کنید که برای هر درخواست یک endpoint از Smartproxy انتخاب میکند، بین استخرهای مسکونی و دیتاسنتری میچرخد، و خطاهای رایج پروکسی را بدون هاردکد کردن اعتبارنامهها در spider شما دوباره تلاش میکند.
Smartproxy از HTTP و SOCKS5 پشتیبانی میکند؛ این راهنما از endpointهای پروکسی HTTP/HTTPS استفاده میکند زیرا میانافزار پروکسی داخلی Scrapy انتظار URLهای پروکسی HTTP را دارد.
پیشنیازها
- یک ماشین یا کانتینر لینوکسی با Python 3.10 یا جدیدتر.
- یک حساب Smartproxy با اعتبارنامههای پروکسی مسکونی و/یا دیتاسنتری.
- جزئیات endpoint از داشبورد Smartproxy: میزبان پروکسی، پورت، نام کاربری و رمز عبور برای هر استخری که قصد استفاده از آن را دارید.
pipوvenvدر دسترس باشند.
مراحل
مرحله ۱ — یک محیط مجازی ایجاد کنید و Scrapy را نصب کنید
python3 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install scrapy python-dotenv
مرحله ۲ — اعتبارنامههای Smartproxy را به عنوان متغیرهای محیطی ذخیره کنید
اعتبارنامهها را در مخزن خود کامیت نکنید.
export SMARTPROXY_RES_HOST='your-residential-host'
export SMARTPROXY_RES_PORT='your-residential-port'
export SMARTPROXY_RES_USERNAME='your-residential-username'
export SMARTPROXY_RES_PASSWORD='your-residential-password'
export SMARTPROXY_DC_HOST='your-datacenter-host'
export SMARTPROXY_DC_PORT='your-datacenter-port'
export SMARTPROXY_DC_USERNAME='your-datacenter-username'
export SMARTPROXY_DC_PASSWORD='your-datacenter-password'
اگر فایل .env را ترجیح میدهید، آن را قبل از شروع Scrapy بارگذاری کنید. فایل را از کنترل نسخه خارج نگه دارید.
مرحله ۳ — پروژه Scrapy را ایجاد کنید
scrapy startproject smartproxy_scrapy
cd smartproxy_scrapy
scrapy genspider example example.com
مرحله ۴ — یک میانافزار چرخش Smartproxy اضافه کنید
فایل smartproxy_scrapy/middlewares.py را ایجاد کنید یا به فایل تولیدشده اضافه کنید. این میانافزار request.meta['proxy'] را قبل از اجرای HttpProxyMiddleware در Scrapy تنظیم میکند.
import os
from urllib.parse import quote
from scrapy import signals
from scrapy.exceptions import NotConfigured
from scrapy.utils.project import get_project_settings
class SmartproxyRotationMiddleware:
'''Route Scrapy requests through Smartproxy residential or datacenter endpoints.'''
def __init__(self, settings):
self.pools = {
'residential': {
'host': settings.get('SMARTPROXY_RES_HOST'),
'port': settings.get('SMARTPROXY_RES_PORT'),
'username': settings.get('SMARTPROXY_RES_USERNAME'),
'password': settings.get('SMARTPROXY_RES_PASSWORD'),
},
'datacenter': {
'host': settings.get('SMARTPROXY_DC_HOST'),
'port': settings.get('SMARTPROXY_DC_PORT'),
'username': settings.get('SMARTPROXY_DC_USERNAME'),
'password': settings.get('SMARTPROXY_DC_PASSWORD'),
},
}
if not any(pool['host'] and pool['port'] for pool in self.pools.values()):
raise NotConfigured('Set at least one Smartproxy pool host and port.')
@classmethod
def from_crawler(cls, crawler):
middleware = cls(crawler.settings)
crawler.signals.connect(middleware.spider_opened, signal=signals.spider_opened)
return middleware
def spider_opened(self, spider):
spider.logger.info('Smartproxy rotation middleware enabled')
def process_request(self, request, spider):
pool_name = request.meta.get('proxy_pool', 'residential')
pool = self.pools.get(pool_name)
if not pool or not pool['host'] or not pool['port']:
return None
host = pool['host']
port = pool['port']
username = quote(pool['username'] or '', safe='')
password = quote(pool['password'] or '', safe='')
if username and password:
proxy_url = f'http://{username}:{password}@{host}:{port}'
else:
proxy_url = f'http://{host}:{port}'
request.meta['proxy'] = proxy_url
request.meta['smartproxy_pool'] = pool_name
return None
مرحله ۵ — میانافزار را قبل از میانافزار پروکسی Scrapy فعال کنید
فایل smartproxy_scrapy/settings.py را ویرایش کنید.
DOWNLOADER_MIDDLEWARES = {
'smartproxy_scrapy.middlewares.SmartproxyRotationMiddleware': 749,
}
HTTPPROXY_ENABLED = True
DOWNLOAD_TIMEOUT = 30
RETRY_HTTP_CODES = [403, 407, 429, 500, 502, 503, 504]
RETRY_TIMES = 2
CONCURRENT_REQUESTS = 16
CONCURRENT_REQUESTS_PER_DOMAIN = 4
HttpProxyMiddleware داخلی Scrapy با ترتیب 750 قرار میگیرد، بنابراین 749 تضمین میکند که میانافزار شما ابتدا URL پروکسی را تنظیم کند.
مرحله ۶ — برای هر درخواست مسکونی یا دیتاسنتری را انتخاب کنید
از meta={'proxy_pool': 'residential'} برای صفحات هدفگیری جغرافیایی یا با ناشناسی بالا استفاده کنید. از meta={'proxy_pool': 'datacenter'} برای صفحات پرحجم و پایدار استفاده کنید.
import scrapy
class SmartproxyDemoSpider(scrapy.Spider):
name = 'smartproxy_demo'
start_urls = ['https://httpbin.org/ip']
def start_requests(self):
for url in self.start_urls:
yield scrapy.Request(
url,
meta={'proxy_pool': 'residential'},
callback=self.parse,
dont_filter=True,
)
yield scrapy.Request(
url,
meta={'proxy_pool': 'datacenter'},
callback=self.parse,
dont_filter=True,
)
def parse(self, response):
yield {
'pool': response.meta.get('smartproxy_pool'),
'status': response.status,
'origin': response.text.strip(),
}
مرحله ۷ — تلاشهای مجدد پشتیبان بین استخرها اضافه کنید
کد 403 یا 429 از سایت هدف اغلب به این معنی است که IP فعلی مسدود شده است. این متد را داخل کلاس SmartproxyRotationMiddleware اضافه کنید تا یک درخواست ناموفق یک بار با استخر دیگر Smartproxy دوباره تلاش شود.
def process_response(self, request, response, spider):
retryable = {403, 429}
already_switched = request.meta.get('smartproxy_pool_retry', False)
if response.status in retryable and not already_switched:
current = request.meta.get('proxy_pool', 'residential')
alternate = 'datacenter' if current == 'residential' else 'residential'
new_meta = request.meta.copy()
new_meta['proxy_pool'] = alternate
new_meta['smartproxy_pool_retry'] = True
spider.logger.warning(
'Retrying %s with %s pool after HTTP %s',
request.url,
alternate,
response.status,
)
return request.replace(meta=new_meta, dont_filter=True)
return response
اگر از این پشتیبان استفاده میکنید، RETRY_TIMES را پایین نگه دارید تا درخواستهای مسدودشده بینهایت حلقه نزنند.
مرحله ۸ — spider را اجرا کنید و نتایج را ذخیره کنید
scrapy crawl smartproxy_demo -O smartproxy_results.json
مرحله ۹ — IP خروجی پروکسی را با cURL بررسی کنید
از همان endpoint HTTP Smartproxy خارج از Scrapy استفاده کنید تا اعتبارنامهها و اتصال را تأیید کنید.
curl --proxy 'http://USERNAME:PASSWORD@HOST:PORT' https://httpbin.org/ip
USERNAME، PASSWORD، HOST و PORT را با مقادیر استخری که در حال آزمایش آن هستید جایگزین کنید.
عیبیابی
407 Proxy Authentication Required: نام کاربری و رمز عبور را بررسی کنید، مطمئن شوید URL-encoded هستند، و تأیید کنید که از میزبان و پورت درست برای استخر انتخابشده استفاده میکنید.Tunnel connection failedیا خطاهای TLS: تأیید کنید که endpoint Smartproxy از هدفهای HTTPS از طریق HTTP CONNECT پشتیبانی میکند. ابتدا آن را با دستور cURL در مرحله ۹ آزمایش کنید.- Scrapy پروکسی را نادیده میگیرد: تأیید کنید که
SmartproxyRotationMiddlewareدرDOWNLOADER_MIDDLEWARESزیر 750 تنظیم شده است، و اینکهHTTPPROXY_ENABLEDبرابرTrueاست. 403یا429مکرر:CONCURRENT_REQUESTS_PER_DOMAINرا کاهش دهید،DOWNLOAD_DELAYاضافه کنید، به پروکسیهای مسکونی سوئیچ کنید، و user agentها را فقط جایی بچرخانید که هدف اجازه میدهد.- پاسخهای کند: پروکسیهای دیتاسنتری معمولاً برای توان عملیاتی خام بهتر هستند؛ پروکسیهای مسکونی برای درخواستهای هدفگیری جغرافیایی و سایتهایی که محدوده IP دیتاسنتر را مسدود میکنند بهترند.
- اعتبارنامهها شامل
@،:، یا/هستند: فراخوانیهایurllib.parse.quoteرا در میانافزار نگه دارید. Quote کردن از URLهای پروکسی بدشکل جلوگیری میکند.
خلاصه
اکنون یک پروژه Scrapy دارید که درخواستها را از طریق پروکسیهای HTTP مسکونی و دیتاسنتری Smartproxy در لینوکس مسیریابی میکند. میانافزار برای هر درخواست یک استخر انتخاب میکند، اعتبارنامهها را در متغیرهای محیطی نگه میدارد، و میتواند وقتی هدفی یک IP را مسدود میکند به استخر دیگر برگردد. با همزمانی پایین شروع کنید، IPهای خروجی خود را با cURL بررسی کنید، و CONCURRENT_REQUESTS_PER_DOMAIN را فقط پس از اینکه خزش بهطور قابلاعتماد رفتار کرد افزایش دهید.