Посилання скопійовано!
ПродуктиЦіниСценаріїРішенняРесурсиКомпаніяFAQ
Почати
Головна Блог Інтеграція проксі з Python
Гайди

Проксі в Python: повний посібник із прикладами коду

Повний посібник із прикладами коду для використання проксі в Python.

Бібліотека requests у Python дає змогу легко спрямовувати трафік через проксі. Цей посібник починається з базового запиту й поступово переходить до сесій, SOCKS5, тайм-аутів, повторних спроб, httpx, паралельних запитів і помилок, які трапляються найчастіше.

У всіх прикладах використано заповнювачі: замініть USERNAME, PASSWORD, HOST і PORT даними свого проксі. Код працює з актуальними версіями Python 3, requests і httpx.

Головне
  • Використовуйте один URL проксі з http:// для трафіку http і https та кодуйте логін і пароль відсотковим кодуванням.
  • Завжди задавайте тайм-аут: за замовчуванням requests чекає нескінченно.
  • Використовуйте одну Session для багатьох запитів, а для SOCKS5 — socks5h://, щоб DNS розв’язував проксі.
  • Повторюйте лише тимчасові помилки з наростаючою затримкою та тримайте паралельні запити в межах лімітів вашого тарифу.
  • Зберігайте облікові дані у змінних середовища й ніколи не виводьте URL проксі.

1.Що потрібно перед початком

Вам потрібні Python 3.9 або новіший, бібліотека requests і дані вашого проксі: хост, порт, логін, пароль і протокол (HTTP(S) або SOCKS5). Встановіть бібліотеку за допомогою pip:

python -m pip install requests

URL проксі має вигляд scheme://username:password@host:port. Для HTTP(S)-проксі схема — http. Символи /, ?, #, %, @ і : мають особливе значення в URL, тому логін і пароль потрібно закодувати відсотковим кодуванням. Це вміє стандартна бібліотека:

from urllib.parse import quote

username = "USERNAME"
password = "p@ss/word#1"        # a password with special characters

proxy = f"http://{quote(username, safe='')}:{quote(password, safe='')}@HOST:PORT"
# -> http://USERNAME:p%40ss%2Fword%231@HOST:PORT

2.Базовий запит через проксі в Python requests

Передайте URL проксі для http і https. Замініть заповнювачі власними даними.

import requests

proxy = "http://USERNAME:PASSWORD@HOST:PORT"
proxies = {"http": proxy, "https": proxy}

r = requests.get("https://example.com", proxies=proxies, timeout=15)
print(r.status_code)

Схема в URL проксі вказує, як ви спілкуєтеся з проксі, а не який сайт відкриваєте. URL проксі з http:// обслуговує і сторінки http://, і https://. Для HTTPS-сторінки requests просить проксі відкрити тунель, і зашифроване з’єднання із сайтом проходить крізь нього без змін.

Перевірте, яку IP-адресу бачить сайт

Наш публічний ендпоінт повертає IP-адресу й країну, які бачить наш сервер для запиту. Дозволено до 30 запитів на хвилину з однієї адреси, нічого не зберігається.

r = requests.get("https://xameleon.cloud/api/tools/ip", proxies=proxies, timeout=15)
print(r.json())    # {'ip': '203.0.113.25', 'country': 'UA'}

Якщо адреса належить оператору, а не вам, проксі використовується.

3.Не зберігайте облікові дані в коді

Не вписуйте логін і пароль безпосередньо в код. Читайте їх зі змінних середовища, щоб вони не потрапляли в репозиторій, журнали й скриншоти.

import os
from urllib.parse import quote

user = quote(os.environ["PROXY_USER"], safe="")
password = quote(os.environ["PROXY_PASS"], safe="")
proxy = f"http://{user}:{password}@{os.environ['PROXY_HOST']}"    # PROXY_HOST is HOST:PORT
proxies = {"http": proxy, "https": proxy}

Задайте змінні в оболонці (export PROXY_USER=... у Linux і macOS, $env:PROXY_USER = "..." у PowerShell) або завантажуйте їх із файлу .env, який виключено з системи контролю версій. Ніколи не виводьте й не записуйте в журнал URL проксі: у ньому є ваш пароль. Докладніше — у матеріалі про безпечне та відповідальне використання проксі.

4.Використовуйте сесію

Сесія повторно використовує з’єднання, що швидше, коли ви надсилаєте багато запитів.

import requests

urls = ["https://example.com/page/1", "https://example.com/page/2"]

with requests.Session() as session:
    session.proxies.update(proxies)
    session.headers.update({"User-Agent": "my-app/1.0 (contact: [email protected])"})

    for url in urls:
        r = session.get(url, timeout=15)
        print(url, r.status_code)

Сесія також зберігає cookie між запитами, а оскільки IP стабільний, кожен запит у ній виходить з тієї самої адреси, поки ви продовжуєте працювати. Блок with закриває з’єднання, коли ви закінчуєте.

Змінні середовища можуть перевизначити проксі сесії

requests також читає HTTP_PROXY, HTTPS_PROXY і NO_PROXY зі змінних середовища. Якщо вони задані, вони мають пріоритет над session.proxies (але не над proxies=, переданим у сам виклик), тому сесія може непомітно скористатися не тим проксі. Передавайте proxies= у кожен запит або вимкніть середовище для сесії:

session.trust_env = False    # ignore HTTP_PROXY, HTTPS_PROXY and NO_PROXY

trust_env = False також змушує requests ігнорувати REQUESTS_CA_BUNDLE і .netrc, тож використовуйте його лише там, де ви на них не покладаєтеся.

Хочете побачити, як це працює для вашого проєкту?
Розкажіть про свій сценарій, і ми запропонуємо налаштування.
Переглянути ціни

5.SOCKS5 проксі в Python

Для SOCKS5 встановіть додатковий пакет і змініть схему в URL проксі.

python -m pip install "requests[socks]"
proxy = "socks5h://USERNAME:PASSWORD@HOST:PORT"
proxies = {"http": proxy, "https": proxy}

r = requests.get("https://example.com", proxies=proxies, timeout=15)
print(r.status_code)

Літера h у socks5h має значення. У socks5:// ваш комп’ютер сам шукає IP-адресу сайту й передає проксі лише число. У socks5h:// до проксі йде ім’я сайту, і розв’язує його вже проксі. Віддавайте перевагу socks5h://: так немає локальних DNS-запитів, і працюють імена, яких ваш комп’ютер не може розв’язати.

Для вебзапитів використовуйте HTTP(S). Обирайте SOCKS5, коли ваш інструмент працює із серверами, що не є сайтами, або підтримує лише SOCKS.

6.Тайм-аути та повторні спроби для проксі в Python

Завжди задавайте тайм-аут і повторюйте тимчасові помилки з наростаючою затримкою.

Тайм-аути

У requests немає тайм-ауту за замовчуванням, тому завислий зв’язок може зупинити вашу програму назавжди. Задавайте timeout у кожному виклику. Одне число діє і для підключення, і для читання, а кортеж задає їх окремо:

# (connect timeout, read timeout) in seconds
r = session.get(url, timeout=(5, 20))

Тайм-аут підключення охоплює з’єднання з проксі та відкриття каналу. Тайм-аут читання — це час очікування наступних байтів відповіді. Стільникові канали додають затримку, тому починайте з щедрих значень і підбирайте їх за власними вимірюваннями.

Повторні спроби з наростаючою затримкою

Повторюйте лише тимчасові проблеми: помилки з’єднання та відповіді на кшталт 429, 502, 503 і 504. Не повторюйте помилки, які самі не зникнуть, як-от 404 чи 407. Бібліотека urllib3 може повторювати запити за вас і чекати довше після кожної невдалої спроби:

import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

retry = Retry(
    total=3,
    backoff_factor=1,                              # wait longer after each failed attempt
    status_forcelist=[429, 500, 502, 503, 504],
    allowed_methods=["GET", "HEAD"],               # retry only requests that are safe to repeat
    respect_retry_after_header=True,
)
adapter = HTTPAdapter(max_retries=retry)

session = requests.Session()
session.proxies.update(proxies)
session.mount("http://", adapter)
session.mount("https://", adapter)

Заголовок Retry-After береться до уваги, а allowed_methods обмежує повтори запитами, які безпечно повторювати. Коли спроби вичерпано, requests викликає RetryError.

Обробляйте помилки

try:
    r = session.get(url, timeout=(5, 20))
    r.raise_for_status()
except requests.exceptions.ProxyError:
    print("The proxy refused, dropped or did not answer the connection")
except requests.exceptions.Timeout:
    print("Timed out: raise the timeout or lower the concurrency")
except requests.exceptions.RequestException as exc:
    print("Request failed:", type(exc).__name__)

Виводьте клас винятку, а не все повідомлення: у повідомленнях можуть бути імена хостів і URL, яким не місце у ваших журналах.

7.Перевірка IP та його зміна

Зі стабільним IP ваші запити виходять з тієї самої адреси, поки ви продовжуєте працювати. Натисніть «Змінити IP» у кабінеті, коли потрібна нова; керування зміною IP через API заплановане. Ця функція читає поточний вихідний IP, тож ви можете переконатися, що зміна відбулася:

import requests

def new_session():
    s = requests.Session()
    s.proxies.update(proxies)
    return s

def exit_ip(session):
    r = session.get("https://xameleon.cloud/api/tools/ip", timeout=(5, 20))
    r.raise_for_status()
    return r.json()["ip"]

session = new_session()
before = exit_ip(session)

input("Press Change IP in your account, then press Enter... ")
session.close()                  # drop connections that still point at the old IP
session = new_session()

after = exit_ip(session)
print("IP changed" if after != before else "Same IP: check that the change went through")

Змінюйте IP між завданнями, а не посеред входу в акаунт чи оформлення замовлення. У матеріалі про ротацію проксі показано шаблони, що поєднують зміну на вимогу з кількома проксі.

8.Проксі з httpx та асинхронний код

httpx працює за тією ж ідеєю з дещо іншим API та підтримкою асинхронності. Передайте проксі клієнтові. Версії httpx старіші за 0.26 приймають proxies= замість proxy=.

import httpx

proxy = "http://USERNAME:PASSWORD@HOST:PORT"
timeout = httpx.Timeout(20.0, connect=5.0)

with httpx.Client(proxy=proxy, timeout=timeout) as client:
    r = client.get("https://example.com")
    print(r.status_code)

Для SOCKS5 встановіть додатковий пакет командою python -m pip install "httpx[socks]" і використовуйте URL із socks5://. Для багатьох одночасних запитів скористайтеся AsyncClient із семафором, щоб кількість одночасних запитів не перевищувала ліміт вашого тарифу:

import asyncio
import httpx

URLS = [f"https://example.com/page/{i}" for i in range(1, 11)]

async def main():
    sem = asyncio.Semaphore(5)                      # at most 5 requests at a time
    async with httpx.AsyncClient(proxy=proxy, timeout=20) as client:

        async def fetch(url):
            async with sem:
                r = await client.get(url)
                return url, r.status_code

        for url, status in await asyncio.gather(*(fetch(u) for u in URLS)):
            print(url, status)

asyncio.run(main())

9.Паралельні запити в межах лімітів

Session не задокументована як потокобезпечна, тому дайте кожному робочому потоку власну сесію. Тримайте max_workers не вище за кількість одночасних з’єднань, яку дозволяє ваш тариф.

import threading
from concurrent.futures import ThreadPoolExecutor

local = threading.local()

def get_session():
    if not hasattr(local, "session"):
        local.session = requests.Session()
        local.session.proxies.update(proxies)
    return local.session

def fetch(url):
    r = get_session().get(url, timeout=(5, 20))
    return url, r.status_code

with ThreadPoolExecutor(max_workers=5) as pool:
    for url, status in pool.map(fetch, urls):
        print(url, status)

Паралельні запити використовують той самий IP і той самий обсяг трафіку. Більше потоків не змушує сайт приймати більше запитів, тож зменшуйте їхню кількість, коли бачите відповіді 429.

10.Типові помилки та як їх виправити

Повідомлення підказує, де шукати причину. Ось помилки, які найчастіше трапляються з requests:

Що ви бачитеІмовірна причинаВиправлення
ProxyError з Tunnel connection failed: 407 Proxy Authentication RequiredНеправильний логін або парольВведіть облікові дані з кабінету ще раз і закодуйте їх. Для звичайних сторінок http:// ви отримаєте відповідь зі статусом 407, а не виняток.
ProxyError з Failed to establish a new connectionНеправильний хост чи порт або не той протоколПеревірте хост, порт і протокол (HTTP чи SOCKS5) точно так, як у кабінеті.
ProxyError з ConnectTimeoutErrorПроксі недоступний із вашої мережіПеревірте хост, брандмауер і мережу. З проксі тайм-аут підключення позначається як ProxyError, а не ConnectTimeout.
ReadTimeoutСайт або мобільне з’єднання відповіли надто повільноЗбільште тайм-аут читання, зменште паралельність і повторіть запит із наростаючою затримкою.
InvalidURL: Failed to parseСпеціальні символи в URL проксіЗакодуйте логін і пароль відсотковим кодуванням за допомогою quote(value, safe="").
InvalidSchema: Missing dependencies for SOCKS supportНе встановлено додаткового пакета SOCKSВиконайте python -m pip install "requests[socks]".
SSLError з CERTIFICATE_VERIFY_FAILEDЗастарілий або корпоративний набір сертифікатів на вашому боціОновіть certifi або вкажіть правильний набір у REQUESTS_CA_BUNDLE. Не вимикайте перевірку через verify=False.
Сайт показує вашу власну IP-адресуПроксі не використовується: задано лише один із ключів http і httpsЗадайте обидва ключі в proxies і перевірте результат викликом ендпоінта IP.

11.Поводьтеся коректно

Додавайте затримки між запитами, дотримуйтесь robots.txt та умов кожного сайту й тримайте паралельність у межах лімітів вашого тарифу.

Щоб перевірити robots.txt через той самий проксі, завантажте його своєю сесією й передайте парсеру зі стандартної бібліотеки:

import random
import time
from urllib.robotparser import RobotFileParser

base = "https://example.com"
r = session.get(base + "/robots.txt", timeout=(5, 20))
robots = RobotFileParser()
robots.parse(r.text.splitlines() if r.ok else [])    # no robots.txt: nothing is disallowed

for path in ["/page/1", "/page/2"]:
    if not robots.can_fetch("my-app", base + path):
        continue                                     # the site asks bots to stay out
    r = session.get(base + path, timeout=(5, 20))
    time.sleep(random.uniform(1, 3))                 # a pause between requests

Позначайте свою програму зрозумілим User-Agent, збирайте лише ті дані, на які маєте право, і читайте умови сайту, з яким працюєте. Бюджет запитів і обробку помилок докладніше розглянуто в матеріалі про веб-скрейпінг у великому масштабі.

12.Часті запитання

Яка бібліотека Python найкраща для роботи з проксі?

requests — найпростіший вибір для скриптів. httpx додає підтримку асинхронності та суворішу модель тайм-аутів. Обидві приймають однаковий URL проксі, тож перейти з однієї на іншу можна, не змінюючи дані проксі.

Чи використовує Python системний проксі автоматично?

requests і httpx за замовчуванням читають змінні середовища HTTP_PROXY, HTTPS_PROXY і NO_PROXY. Щоб їх ігнорувати, задайте trust_env=False.

Що обрати: HTTP чи SOCKS5?

Для вебзапитів використовуйте HTTP(S). SOCKS5 обирайте, коли цього потребує інструмент, і віддавайте перевагу схемі socks5h://.

Як зберегти той самий IP для всіх запитів?

Ваш IP стабільний: він лишається тим самим, поки ви продовжуєте працювати, а коли потрібен новий, ви змінюєте його в кабінеті. Використовуйте одну сесію на завдання й не натискайте «Змінити IP» посеред нього.

Як використовувати кілька проксі в Python?

Створіть окрему сесію для кожного проксі та вибирайте між ними у своєму коді. Шаблони показано в матеріалі про ротацію проксі.

Чи можна використовувати проксі з Playwright?

Так. Передайте проксі під час запуску браузера: proxy={"server": "http://HOST:PORT", "username": "USERNAME", "password": "PASSWORD"}.

Лишилися запитання про мобільні проксі? Відвідайте нашу сторінку FAQ щоб отримати детальні відповіді, або зверніться до нашої підтримки — ми допоможемо.

Проксі в Python: головне та що читати далі

Робота з проксі в Python тримається на кількох надійних звичках. Використовуйте одну сесію для багатьох запитів, задавайте тайм-аут для кожного виклику й не зберігайте облікові дані в коді. Так скрипт лишається швидким, передбачуваним і безпечним для передавання колегам.

Як зробити налаштування проксі в Python requests надійним?

Повторюйте лише тимчасові помилки, як-от тайм-аути та відповіді 429 чи 5xx, і чекайте довше після кожної спроби. Якщо сайт надсилає заголовок Retry-After, дотримуйтесь його. Постійні помилки, як-от 404, повторювати не варто. Для SOCKS5 використовуйте схему socks5h, щоб імена хостів розв’язував сам проксі, а логін і пароль беріть зі змінних середовища, а не з коду. Наші 4G мобільні проксі підтримують HTTP(S) і SOCKS5, тож після встановлення додаткового пакета для SOCKS той самий скрипт може перемикати протокол зміною схеми в URL проксі.

Куди рухатися після першого робочого скрипта

Далі додайте ротацію: посібник про автоматичну ротацію проксі показує, як перебирати кілька проксі в коді, а матеріал про веб-скрейпінг у масштабі розповідає про ліміти запитів і обробку помилок. Якщо створюєте інструменти збору даних, дивіться проксі для веб-скрейпінгу і порівняйте тарифи на сторінці цін на мобільні проксі.