Ротация прокси в Scrapy: как ротировать прокси в Scrapy (и когда выделенный шлюз WireGuard лучше)
Реализуйте ротацию прокси в Scrapy с помощью собственного middleware, корректно обрабатывайте блокировки и узнайте, когда стабильный шлюз WireGuard, например NordLayer, — правильный выбор для SEO-мониторинга и веб-скрапинга.
Обзор
Веб-скрапинг в больших масштабах часто сталкивается с ограничениями скорости, блокировками IP или геоограничениями. Scrapy, популярный Python-фреймворк, не ротирует прокси из коробки. В этом руководстве показано, как создать middleware для ротации прокси в Scrapy, настроить повторные попытки и решить, когда выделенный VPN-шлюз WireGuard (например, NordLayer) подходит лучше, чем пул ротируемых прокси.
Вы узнаете о двух подходах:
- Ротируемые прокси: используйте множество IP в рамках сессии, чтобы распределять запросы и избегать блокировок.
- Выделенный шлюз WireGuard: используйте один стабильный IP для задач, требующих постоянства, например отслеживания позиций, проверки рекламы или доступа к геозависимому контенту, который плохо переносит смену IP.
NordLayer предоставляет WireGuard-туннели корпоративного уровня с выделенными шлюзами и фиксированной ежемесячной оплатой. Это не сервис ротируемых прокси, но он может служить стабильным исходящим IP для ваших Scrapy-пауков, когда важна согласованность.
Предварительные требования
- Python 3.7 или новее
- Базовое знакомство со Scrapy
- Список HTTP/HTTPS- или SOCKS5-прокси (для подхода с ротацией)
- Необязательно: аккаунт NordLayer с выделенным шлюзом WireGuard (для подхода со стабильным IP)
- Linux-сервер или локальная машина (команды приведены для Debian/Ubuntu; адаптируйте под другие системы)
Понимание ротации прокси в Scrapy
Scrapy использует middleware загрузчика для обработки запросов и ответов. Чтобы ротировать прокси, вы перехватываете каждый запрос, назначаете прокси из пула и при необходимости повторяете попытку с новым прокси, если запрос не удался.
Ключевые понятия:
- Пул прокси: список URL прокси (при необходимости с учетными данными).
- Стратегия ротации: случайный выбор, по кругу или взвешенный по работоспособности прокси.
- Логика повторных попыток: повторная постановка неудавшихся запросов в очередь с другим прокси.
Когда вместо этого стоит рассмотреть выделенный шлюз WireGuard:
- Вам нужен постоянный IP для отслеживания позиций SEO в нескольких локациях.
- Целевой сайт блокирует частую смену IP агрессивнее, чем статические IP.
- Вы хотите зашифрованный доступ с управлением для команды без поддержки списка прокси.
Шаги
1. Установите Scrapy и создайте проект
Если вы еще этого не сделали, установите Scrapy и создайте каркас нового проекта.
pip install scrapy
scrapy startproject proxy_scraper
cd proxy_scraper
scrapy genspider example example.com
2. Создайте middleware для ротации прокси
Откройте proxy_scraper/middlewares.py и добавьте следующий middleware. Он выбирает случайный прокси для каждого запроса и повторяет попытку при типичных кодах состояния блокировки.
# 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
3. Настройте параметры, чтобы включить middleware и задать прокси
Отредактируйте proxy_scraper/settings.py, чтобы активировать middleware и указать свой список прокси. Замените примеры прокси на свои.
# 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]
4. Проверьте ротацию с помощью простого паука
Запустите паука и следите за логами DEBUG, чтобы убедиться, что используются разные прокси.
scrapy crawl example -L DEBUG
Если вы видите строки вроде Using proxy: http://..., middleware работает. Если все запросы используют один и тот же прокси, проверьте порядок middleware и то, что ROTATING_PROXY_LIST не пуст.
5. Повысьте надежность с помощью проверок работоспособности и 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
6. Когда переходить на выделенный шлюз WireGuard
Ротируемые прокси отлично подходят для крупномасштабного скрапинга без сохранения состояния. Но некоторым задачам нужен стабильный выделенный IP:
- Отслеживание позиций SEO, где нужны согласованные данные о местоположении
- Доступ к API, которые привязывают сессии к IP
- Командный скрапинг, где несколько пользователей используют один и тот же исходящий IP
WireGuard-туннели NordLayer дают вам выделенный шлюз с фиксированной ежемесячной оплатой. Вы можете направлять весь трафик Scrapy через туннель, фактически используя один статический IP.
7. Настройте WireGuard в Linux и направьте 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 шлюза.
8. Комбинируйте подходы для гибридного скрапинга
Вы можете использовать оба подхода: направлять большинство запросов через ротируемые прокси, но отправлять запросы, которым нужен постоянный 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'})
Затем измените middleware, чтобы пропускать ротацию, когда proxy == 'direct':
def process_request(self, request, spider):
if request.meta.get('proxy') == 'direct':
return None # use default route
# ... rest of rotation logic
Устранение неполадок
- Middleware не применяется: убедитесь, что
DOWNLOADER_MIDDLEWARESсодержит правильный путь и что значение (543) не конфликтует с другими middleware. Проверьте порядок middleware по умолчанию в Scrapy. - Все запросы по-прежнему используют один IP: проверьте, что
ROTATING_PROXY_LISTзаполнен и чтоprocess_requestmiddleware выполняется. Добавьтеprintили отладочный лог. - Частые ошибки 403/429: ваши прокси могут быть заблокированы или слишком медленны. Уменьшите
CONCURRENT_REQUESTSиDOWNLOAD_DELAYили перейдите на более качественные прокси. Рассмотрите выделенный шлюз WireGuard, если целевой сайт агрессивно блокирует ротируемые IP. - Туннель WireGuard не подключается: перепроверьте приватный ключ, публичный ключ, endpoint и правила фаервола (по умолчанию UDP-порт 51820). Выполните
sudo wg show, чтобы увидеть статус рукопожатия. - Scrapy игнорирует туннель WireGuard: если вы задали
AllowedIPs = 0.0.0.0/0, весь трафик должен идти через туннель. Подтвердите с помощьюip routeи проверьте черезcurl ifconfig.me.
Итог
Теперь вы знаете, как реализовать ротацию прокси в Scrapy с помощью собственного middleware, добавить логику повторных попыток и отслеживать работоспособность прокси. Для проектов, требующих стабильного выделенного IP — например, отслеживания позиций SEO или командного доступа — шлюз WireGuard, такой как NordLayer, может дополнить или заменить ротируемые прокси. Выбирайте подход, соответствующий вашим целям скрапинга: ротация для масштаба и анонимности, выделенные шлюзы для постоянства и контроля.