Socks5Proxy

Настройка прокси в Scrapy: использование meta proxy для разных IP в каждом запросе

Это руководство объясняет, как подключить HTTP-прокси Socks5Proxy через meta proxy в Scrapy, циклически использовать список, полученный через API, в middleware загрузчика, и настроить скорость для целевого сайта.

Как Scrapy обрабатывает прокси?

В Scrapy по умолчанию включен HttpProxyMiddleware. Если добавить адрес прокси в meta-словарь запроса с ключом proxy, запрос пойдет через этот прокси, а логин и пароль из адреса middleware автоматически преобразует в заголовок Proxy-Authorization. HTTPS-адреса передаются через CONNECT-туннель.

Стандартный обработчик загрузки Scrapy поддерживает HTTP-прокси. Если вам обязательно нужен SOCKS5, потребуется дополнительный обработчик, поэтому в Scrapy мы рекомендуем использовать HTTP-порт того же IP. Целевой сайт увидит тот же IP.

Пример использует IP 198.51.100.23, HTTP-порт 8000, имя пользователя spx_user, пароль spx_pass.

pip install scrapy
scrapy startproject shop
cd shop

Как добавить прокси в один запрос?

Добавьте proxy в meta при создании Request в start_requests. В callback для запроса следующей страницы используйте тот же метод. Чтобы сохранить сессию, передавайте proxy из meta предыдущего ответа - это сохранит IP.

import scrapy

PROXY = "http://spx_user:spx_pass@198.51.100.23:8000"

class IpCheckSpider(scrapy.Spider):
    name = "ip_check"

    def start_requests(self):
        yield scrapy.Request("https://api.ipify.org?format=json", meta={"proxy": PROXY})

    def parse(self, response):
        self.logger.info("seen as %s", response.json()["ip"])

Как ротировать IP для каждого запроса?

Создайте промежуточное ПО для загрузки, которое будет добавлять прокси ко всем запросам, и вы сможете ротировать их без изменения кода паука. Пример ниже загружает список через API при запуске и сохраняет существующий proxy в meta, позволяя сочетать фиксацию сессии и ротацию.

API-ключи можно разместить в settings.py или читать из переменных окружения. Регистрируйте их с числом, меньшим чем у HttpProxyMiddleware(750), чтобы базовый middleware обрабатывал адреса, добавленные middleware.

import itertools
import requests

class RotatingProxyMiddleware:
    def __init__(self, key):
        text = requests.get(
            "https://socks5proxy.io/api/v1/proxies/download",
            params={"format": "user:pass@ip:port", "protocol": "http"},
            headers={"Authorization": "Bearer " + key},
            timeout=30,
        ).text
        self.pool = itertools.cycle(["http://" + l.strip() for l in text.splitlines() if l.strip()])

    @classmethod
    def from_crawler(cls, crawler):
        return cls(crawler.settings.get("SPX_API_KEY"))

    def process_request(self, request, spider):
        if "proxy" not in request.meta:  # keep a proxy that was set on purpose (sticky sessions)
            request.meta["proxy"] = next(self.pool)

Как настроить скорость и повторные попытки?

CONCURRENT_REQUESTS_PER_DOMAIN - количество одновременных запросов к одному домену. Чем больше прокси-IP, тем выше можно установить это значение без увеличения нагрузки на один IP. Например, при 500 IP и 50 одновременных запросах каждый IP будет использоваться в среднем один раз на 10 запросов.

Включите AUTOTHROTTLE для автоматической регулировки интервалов запросов по скорости ответа. При увеличении ответов 429 используйте RETRY_HTTP_CODES для повторных попыток, но можно также удалить proxy из meta при повторной попытке, чтобы middleware использовал следующий прокси.

Добавление этапа проверки, что собранные данные - реальные страницы, а не подтверждения, улучшит качество данных. Ответы без нужных элементов можно запросить повторно с другого IP.

  • Настройка количества одновременных запросов на домен в зависимости от числа IP
  • AUTOTHROTTLE для автоматической регулировки интервалов по скорости ответа
  • При 429 и 5xx ошибках попробуйте другой IP
  • Проверка содержимого ответа для фильтрации капчи

Что меняется при подключении с авторизацией по IP?

Если зарегистрировать IPv4 сервера, где запущен Scrapy, в панели управления, то можно использовать meta proxy без логина и пароля, например http://198.51.100.23:8000. Список можно получить в формате ip:port. Если вы запускаете пауков на нескольких серверах, зарегистрируйте IP каждого сервера. Можно зарегистрировать до 10 IP.

Как связать запросы, требующие сессии, с одним IP?

Для последовательностей с куки, таких как вход в систему или корзина покупок, используйте один и тот же IP. Укажите meta proxy в первом запросе, а в callback передавайте значение proxy из response.meta, чтобы ротационное middleware не меняло его. Использование cookiejar meta key в Scrapy также помогает разделять куки по сессиям.

Если связать один прокси и один набор cookies с одной сессией, несколько сессий могут работать одновременно, не смешиваясь.

import scrapy

PROXIES = [
    "http://spx_user:spx_pass@198.51.100.23:8000",
    "http://spx_user:spx_pass@198.51.100.24:8000",
]

class SessionSpider(scrapy.Spider):
    name = "sessions"

    def start_requests(self):
        for i, proxy in enumerate(PROXIES):
            yield scrapy.Request("https://example.com/", meta={"proxy": proxy, "cookiejar": i}, dont_filter=True)

    def parse(self, response):
        # follow-up request keeps the same proxy and the same cookie jar
        yield response.follow("/account", meta={"proxy": response.meta["proxy"], "cookiejar": response.meta["cookiejar"]}, callback=self.parse_account)

    def parse_account(self, response):
        self.logger.info("status %s via %s", response.status, response.meta["proxy"])

Как временно исключить проблемный прокси?

Если middleware получает ответ 403 или 429, можно временно отключить этот прокси на несколько минут и отправить тот же запрос через другой прокси. Скопируйте запрос, удалите proxy из meta, включите dont_filter и верните его - следующий прокси возьмёт его в работу.

Управление списком отдыхающих прокси и временем их повторного использования можно упростить с помощью словаря. Избегая повторного использования одних и тех же IP, вы даёте сайтам время снять ограничения.

Какие настройки Scrapy помогают экономить трафик?

Scrapy по умолчанию загружает только HTML и использует значительно меньше трафика, чем инструменты для браузеров. Встроенный HttpCompressionMiddleware поддерживает сжатие ответов, что еще больше сокращает объем передачи. Поэтому даже на общих тарифах можно собрать много страниц в рамках месячного лимита трафика.

Чтобы избежать повторных загрузок одной страницы, включите HTTPCACHE_ENABLED во время разработки - это избавит от лишних запросов к сайту и прокси. В продакшене оставьте фильтрацию дублей (включена по умолчанию) и используйте dont_filter только для запросов, которые действительно нужно повторить.

Важно ограничивать глубину парсинга, чтобы не переходить на ненужные страницы. Это экономит время, трафик и снижает нагрузку на сайт.

Как решить распространенные проблемы?

При ответе 407 проверьте имя пользователя и пароль в адресе. Если в пароле есть специальные символы, используйте процентное кодирование. TunnelError означает, что прокси не получил CONNECT запрос - проверьте, используете ли вы HTTP порт.

Если все запросы идут с одного IP, возможно, middleware стоит после HttpProxyMiddleware или spider напрямую использует meta proxy. Проверьте порядок в settings.py и код spider.

Настройка прокси в Scrapy: meta proxy и ротирующий middleware | Socks5Proxy