Блог
ГлавнаяБлог → Смена IP в Python

Автоматизация смены IP в Python: requests, Selenium, Playwright

17 августа 2026 · 9 минут чтения

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

Как это устроено

Схема одинаковая для любого инструмента и состоит из двух независимых частей:

Отсюда важное следствие: переписывать настройки прокси после смены адреса не нужно. Единственное, о чём стоит помнить, — открытые keep-alive соединения после переподключения модема становятся нерабочими, поэтому сессию после ротации лучше пересоздавать.

requests: базовая обёртка

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

import time, threading
import requests

class MobileProxy:
    def __init__(self, proxy_url, rotate_url):
        self.proxies = {"http": proxy_url, "https": proxy_url}
        self.rotate_url = rotate_url
        self.lock = threading.Lock()
        self.session = requests.Session()

    def current_ip(self, timeout=15):
        r = self.session.get("https://api.ipify.org",
                             proxies=self.proxies, timeout=timeout)
        return r.text.strip()

    def rotate(self, wait_max=40):
        """Меняет IP и ждёт, пока адрес реально изменится."""
        with self.lock:  # ротацию выполняет только один поток
            try:
                old = self.current_ip()
            except requests.RequestException:
                old = None

            requests.get(self.rotate_url, timeout=30)
            self.session.close()
            self.session = requests.Session()  # сбрасываем keep-alive

            deadline = time.time() + wait_max
            while time.time() < deadline:
                time.sleep(3)
                try:
                    new = self.current_ip(timeout=10)
                except requests.RequestException:
                    continue  # канал ещё поднимается
                if new != old:
                    return new
            raise TimeoutError("IP не сменился за отведённое время")

    def get(self, url, retries=3, **kwargs):
        for attempt in range(retries):
            try:
                return self.session.get(url, proxies=self.proxies,
                                        timeout=20, **kwargs)
            except requests.RequestException:
                if attempt == retries - 1:
                    raise
                self.rotate()  # на ошибке — новый адрес и повтор

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

Асинхронный сбор на aiohttp

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

import asyncio, aiohttp

PROXY = "http://user:pass@195.24.10.15:8000"
sem = asyncio.Semaphore(5)  # не больше 5 одновременных запросов

async def fetch(session, url):
    async with sem:
        try:
            async with session.get(url, proxy=PROXY, timeout=20) as r:
                return await r.text()
        except Exception:
            return None

async def main(urls):
    async with aiohttp.ClientSession() as session:
        results = []
        # пачками по 50 URL, между пачками — ротация
        for i in range(0, len(urls), 50):
            batch = urls[i:i + 50]
            results += await asyncio.gather(*(fetch(session, u) for u in batch))
            await asyncio.sleep(1)
        return results

Про параллельность. Мобильный канал — это один модем, а не пул серверов. Пять-десять одновременных соединений он держит спокойно, сотня приведёт к таймаутам и не ускорит сбор. Если нужно больше — берите несколько портов и распределяйте задачи между ними.

Selenium: прокси с авторизацией

Здесь всех ждёт неприятный сюрприз: Chrome через стандартный ключ --proxy-server не умеет принимать логин и пароль. При запуске браузер покажет системное окно ввода, и автоматизация встанет. Есть три выхода:

Способ Как работает Когда подходит
Белый список IP Добавляете адрес своего сервера в панели провайдера, пароль не нужен вовсе Самый простой и надёжный вариант, если у машины статичный адрес
Расширение Генерируете на лету расширение, которое подставляет учётные данные Когда белый список недоступен, а нужен чистый Selenium
selenium-wire Библиотека проксирует трафик и сама решает вопрос авторизации Быстрое решение для скриптов, где не критичен лишний слой
# Вариант с белым списком: пароль не требуется
from selenium import webdriver

options = webdriver.ChromeOptions()
options.add_argument("--proxy-server=http://195.24.10.15:8000")
driver = webdriver.Chrome(options=options)

# Ротация между сессиями: закрыли браузер, сменили IP, открыли заново
driver.quit()
proxy.rotate()
driver = webdriver.Chrome(options=options)

Playwright: проще всего

В Playwright авторизация на прокси предусмотрена из коробки — отдельными полями, без всяких расширений. Это самый удобный вариант, если вы только выбираете инструмент.

from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(proxy={
        "server": "http://195.24.10.15:8000",
        "username": "user",
        "password": "pass",
    })
    page = browser.new_page()
    page.goto("https://api.ipify.org")
    print(page.content())
    browser.close()

Выделенные 4G-порты с REST API для ротации, авторизацией по логину или белому списку IP и безлимитным трафиком.

Арендовать 4G-прокси

Один порт с ротацией или пул портов

Развилка, к которой приходят все, когда объём вырастает. Ротация одного порта — это последовательная работа: пока модем переподключается, скрипт стоит. Восемь секунд простоя после каждой пачки запросов кажутся мелочью, но на тысяче ротаций превращаются в два часа ожидания.

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

import itertools

ports = [MobileProxy(p, r) for p, r in CONFIG]  # несколько портов
pool = itertools.cycle(ports)

def fetch(url):
    for _ in range(len(ports)):
        proxy = next(pool)
        if proxy.lock.locked():   # этот порт сейчас ротируется
            continue
        return proxy.get(url)
    time.sleep(5)               # все заняты — короткая пауза
    return fetch(url)

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

Что стоит логировать

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

Минимальный набор полей в лог: время запроса, внешний IP на момент сбора, URL, код ответа, число попыток. Этого достаточно, чтобы отличить проблему канала от проблемы целевого сайта и понять, не слишком ли часто вы ротируете.

Типичные ошибки

Частые вопросы

Нужно ли пересоздавать соединение после смены IP?

Настройки прокси не меняются, но keep-alive соединения после переподключения мертвы — сессию лучше создать заново.

Как проверить, что IP сменился?

Запросить внешний адрес через тот же прокси до и после ротации и сравнить. Если адрес прежний, повторите вызов через паузу.

Почему Selenium не принимает прокси с паролем?

Chrome через --proxy-server не поддерживает авторизацию. Решения: белый список IP, расширение с учётными данными или selenium-wire.

Сколько ждать после ротации?

Переподключение занимает 3–8 секунд, безопасная пауза — около 10. Надёжнее опрашивать адрес в цикле до фактической смены.

Можно ли ротировать из нескольких потоков?

Не нужно: модем переподключится один раз. Оберните ротацию блокировкой, чтобы её выполнял один поток.