Skip to content
Advanced / 3 min read

Ротация прокси в Scrapy: как ротировать прокси в Scrapy (и когда выделенный шлюз WireGuard лучше)

Реализуйте ротацию прокси в Scrapy с помощью собственного middleware, корректно обрабатывайте блокировки и узнайте, когда стабильный шлюз WireGuard, например NordLayer, — правильный выбор для SEO-мониторинга и веб-скрапинга.

Linux WireGuard Веб-скрейпинг 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_request middleware выполняется. Добавьте 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, может дополнить или заменить ротируемые прокси. Выбирайте подход, соответствующий вашим целям скрапинга: ротация для масштаба и анонимности, выделенные шлюзы для постоянства и контроля.