Руководство по Python · 2 мин чтения

Как делать ротацию прокси в Python (requests и aiohttp)

Ротация — это разница между скрапером, ловящим бан на один IP, и тем, который распределяет нагрузку между многими. Показываем рабочий ротатор для синхронного requests и асинхронного aiohttp, с проверкой живучести и автоматическим выводом мёртвых узлов.

Что на самом деле даёт ротация

Сайты ограничивают и банят по IP. Если все запросы уходят с одного адреса, лимит наступает быстро, а один бан останавливает всю работу. Ротация раскидывает запросы по пулу выходов: нагрузка на каждый IP остаётся под порогом, а мёртвый или заблокированный выход стоит вам всего одной повторной попытки, а не всего запуска. Двух схем хватает почти на всё: round-robin (перебираем пул по кругу — предсказуемо и равномерно) и random (выбираем на каждый запрос — просто и без состояния).

Сам пул можно взять из двух мест. Можно перечислить несколько эндпоинтов и портов s4m и ротировать между ними, а для быстрых неважных тестов — вытащить живые записи из бесплатного публичного списка прокси с фильтрами по стране, протоколу и анонимности; правда, эти сторонние прокси используются на свой страх и риск и часто умирают. Продакшн-ротация должна опираться на аутентифицированные прокси дата-центра от s4m (SOCKS5 на 1080, HTTP на 3128, USER:PASS): они держатся и тарифицируются по трафику, так что расширять пул дёшево. Это прямое продолжение руководства скрапинг с помощью requests.

Ротатор для requests и aiohttp

Пул, который ходит по кругу, повторяет запрос после сбоя и списывает выходы, которые падают раз за разом. Синхронная и асинхронная версии. Подставьте свои USER:PASS.

python
import asyncio, itertools, random
import requests, aiohttp
from aiohttp_socks import ProxyConnector  # pip install aiohttp-socks

USER, PASS, HOST = "USER", "PASS", "proxy.s4m.online"
POOL = [
    f"socks5h://{USER}:{PASS}@{HOST}:1080",
    f"http://{USER}:{PASS}@{HOST}:3128",
    # add more endpoints/ports here to widen the pool
]

# ---------- Synchronous: requests + round-robin + retirement ----------
class Rotator:
    def __init__(self, pool):
        self.alive = list(pool)
        self.fails = {p: 0 for p in pool}
        self._cycle = itertools.cycle(self.alive)

    def pick(self):
        return next(self._cycle)

    def retire(self, proxy):
        self.fails[proxy] += 1
        if self.fails[proxy] >= 3 and proxy in self.alive:
            self.alive.remove(proxy)
            self._cycle = itertools.cycle(self.alive or POOL)

def get(url, rot, retries=4):
    for _ in range(retries):
        proxy = rot.pick()
        try:
            r = requests.get(url, proxies={"http": proxy, "https": proxy},
                             timeout=(5, 20))
            r.raise_for_status()
            return r
        except requests.RequestException:
            rot.retire(proxy)
    raise SystemExit("pool exhausted")

rot = Rotator(POOL)
print(get("https://api.ipify.org", rot).text)

# ---------- Async: aiohttp, one connector per proxy ----------
async def fetch(url, proxy):
    connector = ProxyConnector.from_url(proxy)
    async with aiohttp.ClientSession(connector=connector) as s:
        async with s.get(url, timeout=aiohttp.ClientTimeout(total=25)) as r:
            return await r.text()

async def main():
    tasks = [fetch("https://api.ipify.org", random.choice(POOL))
             for _ in range(5)]
    for ip in await asyncio.gather(*tasks, return_exceptions=True):
        print(ip)

asyncio.run(main())

Решения, которые действительно важны

Настройки, от которых зависит, поможет ротация или только добавит суеты.

Round-robin против random

Round-robin распределяет нагрузку равномерно, и его легко держать в голове; random не имеет состояния и проще. Оба лучше одного фиксированного выхода — берите round-robin, когда важна равномерность.

Списывайте мёртвые выходы

Считайте неудачи подряд по каждому прокси и выбрасывайте выход после нескольких промахов — тогда пул лечит себя сам, а не бьётся вечно в мёртвый адрес.

Проверяйте перед использованием

Периодически обращайтесь через каждый прокси к эндпоинту, который возвращает ваш IP, и оставляйте только те, что отвечают. Обязательно, если в пуле есть нестабильные записи из бесплатного списка.

Отступайте, а не гоните

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

Липкие сессии и честные границы

Ротация нужна не всегда. Некоторые сценарии — вход в аккаунт, корзина, многошаговая форма — требуют одного IP на всю сессию, иначе сайт видит пользователя, который телепортируется между адресами, и блокирует его. Это и есть липкая сессия: ротируйте между задачами и держите фиксированный выход внутри одной. Когда процессу нужен один гарантированно стабильный адрес, вместо ротации добавьте выделенный персональный IP.

О потолке честно. Прокси s4m — дата-центровые, поэтому ротация помогает с лимитами запросов и равномерной нагрузкой, но не спрячет IP дата-центра от антибот-системы, которая блокирует весь диапазон. Ротация так же ничего не делает с отпечатком браузера или паттернами запросов. Воспринимайте её как один слой: добавьте правдоподобные заголовки, отступы и уважение к правилам каждого сайта. Для асинхронной части понадобится aiohttp-socks для поддержки SOCKS5; проверяйте выходы инструментами, а работу с учётными данными автоматизируйте через API.

FAQ

Ответы на вопросы

Как ротировать прокси с requests?

Держите список URL прокси и выбирайте один на каждый запрос — по кругу или случайно — передавая его в аргументе proxies. Списывайте выход после нескольких неудач подряд, чтобы пул лечил себя сам. Пример выше — полноценный ротатор.

Как ротировать прокси с aiohttp?

Для HTTP aiohttp задаёт прокси на каждый запрос, а для SOCKS5 приходится создавать ProxyConnector (из aiohttp-socks) под каждый прокси и делать с ним сессию. Раскидывайте задачи по пулу через asyncio.gather.

Когда прокси ротировать НЕ нужно?

Когда процессу нужна постоянная личность — входы в аккаунт, корзины, многошаговые формы. Смена IP посреди сессии выглядит подозрительно и ведёт к блокировке. Для таких сценариев берите липкую сессию или выделенный IP.

Спасёт ли ротация прокси дата-центра от всех блокировок?

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

Ротируйте по настоящим выходам

Расширьте пул аутентифицированными прокси SOCKS5 и HTTP дата-центра на proxy.s4m.online — с оплатой за трафик, так что масштабироваться дёшево. Для шагов с липкой сессией добавьте выделенный IP.

Эту страницу нашли по запросу

Реальные поисковые фразы, на которые отвечает эта страница — по ссылкам откроются материалы, раскрывающие тему глубже.