Настройка прокси в Scrapy
В Scrapy поддержка прокси уже встроена: HttpProxyMiddleware включён по умолчанию, ставить ничего не нужно. Прокси задаётся через переменные окружения, на отдельный запрос через meta['proxy'] или — самый подходящий для парсинга вариант — небольшим middleware, который ротирует прокси из вашего списка. Логин и пароль передаются прямо в URL прокси — это заодно закрывает вопрос авторизации.
Перед настройкой: данные прокси и порты
Вам понадобятся IP-адрес прокси и порт. И то и другое есть в личном кабинете — откройте активную подписку, там указаны все данные для подключения. Scrapy работает только с HTTP-прокси (встроенной поддержки SOCKS нет), поэтому нужен один из двух HTTP-портов:
| Авторизация | Порт HTTP | Формат URL прокси |
|---|---|---|
| Логин / пароль данные из личного кабинета |
8080 |
http://логин:пароль@IP:8080 |
| Привязка по IP логин и пароль не нужны |
8085 |
http://IP:8085 |
При работе с привязкой сначала добавьте IP-адрес сервера в привязку в личном кабинете. После этого прокси принимает запросы с этой машины без логина и пароля — URL короче, и никаких секретов в проекте.
Быстрый способ: переменные окружения
HttpProxyMiddleware понимает стандартные переменные http_proxy и https_proxy — задайте обе с одним и тем же прокси, и через него пойдут все запросы краулера без единой правки кода:
Обратите внимание: https_proxy отвечает за запросы к https://-адресам — то есть за почти весь современный веб, — но её значение всё равно начинается с http://: это тот же прокси, к которому клиент обращается по тому же протоколу.
На отдельный запрос: meta['proxy']
Для управления изнутри паука передайте прокси в meta запроса — это значение имеет приоритет над переменными окружения:
Этот паук заодно служит проверкой подключения: запустите его — и в логе появится IP прокси вместо вашего.
Логин и пароль должны быть в URL внутри meta['proxy'], а не в самодельном заголовке Proxy-Authorization. Начиная с Scrapy 2.6.2 middleware управляет этим заголовком сам — в том числе стирает его, когда редирект или повтор запроса меняет прокси, чтобы ваши данные не утекли третьей стороне. Если в пароле есть спецсимволы, закодируйте их percent-encoding (@ → %40).
Загрузка прокси из списка и ротация
С пакетом прокси адреса никто не вписывает в код руками: выгрузите весь список из личного кабинета в файл — по одному IP:порт на строку, порядок полей и разделитель настраиваются при выгрузке — и поручите downloader middleware назначать прокси каждому запросу:
middlewares.py
settings.py
Число порядка должно быть меньше 750 — на этой позиции стоит встроенный HttpProxyMiddleware, и он должен сработать после вашего middleware, чтобы подхватить значение из meta['proxy']. Теперь каждый запрос получает случайный IP из списка; если нужен строгий круговой перебор, замените random.choice на itertools.cycle. Поскольку данные для входа передаются внутри URL прокси, одна пара констант покрывает весь список — а если файл выгружен уже с ними (строки вида логин:пароль@IP:порт, формат выгрузки в личном кабинете настраивается), уберите константы и подставляйте строку как есть.
Наши пакеты серверных прокси начинаются от 100 IP, так что сам список узким местом не станет, а когда целевой сайт начнёт ограничивать запросы — обновите список по запросу и выгрузите файл заново. Если управлять ротацией в коде не хочется вовсе, ротационные прокси переворачивают логику: в meta['proxy'] остаётся один адрес шлюза, а выходной IP меняется на каждом запросе.
А что с SOCKS5?
Загрузчик Scrapy построен на Twisted и умеет работать только с HTTP-прокси — встроенной поддержки SOCKS5 нет, а обходные пути (локальные форвардеры, конвертирующие HTTP в SOCKS) добавляют лишнее звено, которое вам не нужно. В каждый пакет PapaProxy.net входит доступ по HTTP, HTTPS, SOCKS4 и SOCKS5 на одних и тех же IP, так что для Scrapy просто используйте HTTP-порты из таблицы выше.
Если что-то не работает
Самые частые причины: ответ 407 Proxy Authentication Required означает, что логин и пароль неверны, отсутствуют в URL или IP машины не добавлен в привязку на порту 8085; TunnelError или ConnectionRefusedError обычно значат, что порт не соответствует способу авторизации (см. таблицу); если запросы к https://-сайтам идут мимо прокси — вместе с http_proxy не задана https_proxy; а если middleware ротации будто игнорируется — проверьте, что его порядок в DOWNLOADER_MIDDLEWARES меньше 750. Если дело не в этом — напишите нам в онлайн-чат прямо на этой странице, поможем подключиться.