Работа с HTTP в Python: практическое применение requests

Раздел: Сетевое программирование -> HTTP

Основные методы работы с HTTP запросами в Python

Библиотека requests предоставляет удобный интерфейс для отправки HTTP запросов. Установка выполняется командой pip install requests. После импорта (import requests) можно вызывать методы get() и post(). Эти методы возвращают объект ответа, содержащий статус код, заголовки, тело и другую информацию.


import requests

# GET запрос
response = requests.get('https://httpbin.org/get')
print(response.status_code)
print(response.text)

# POST запрос с JSON данными
payload = {'key': 'value'}
response = requests.post('https://httpbin.org/post', json=payload)
print(response.json())

Python requests get (get-запрос через requests в python)

Пояснение: метод get() отправляет GET запрос, post() отправляет POST запрос. Аргумент json автоматически сериализует словарь в JSON и устанавливает заголовок Content-Type: application/json. Ответ можно прочитать как текст (.text), как JSON (.json()), или как байты (.content).

Типичная проблема: при вызове .json() на не JSON ответе возникает исключение ValueError. Решение: проверять статус код (response.raise_for_status()) или использовать try-except.


try:
    data = response.json()
except ValueError:
    print('Ответ не содержит JSON')

Get html python (получение html-содержимого через http в python)

Цель: базовое получение и отправка данных через HTTP.

Как отправить GET запрос с параметрами?

Для передачи параметров запроса используется аргумент params, который принимает словарь или список кортежей.


params = {'q': 'python requests', 'page': 1}
response = requests.get('https://httpbin.org/get', params=params)
print(response.url)  # https://httpbin.org/get?q=python+requests&page=1

Url запрос python (работа с url в python)

Пояснение: библиотека самостоятельно кодирует параметры и добавляет их к URL. Если значение параметра None, оно будет пропущено.

Ошибка: при передаче параметров с кириллицей может некорректно кодироваться. Решение: requests кодирует в UTF-8 по умолчанию, но можно передать уже закодированную строку.

Как отправить POST запрос с JSON или формой?

Для JSON используется аргумент json, для формы data.


# JSON
response = requests.post('https://httpbin.org/post', json={'key': 'value'})
# Форма (application/x-www-form-urlencoded)
response = requests.post('https://httpbin.org/post', data={'key': 'value'})
# Форма с файлом (multipart)
files = {'file': ('filename.txt', b'content')}
response = requests.post('https://httpbin.org/post', files=files)

Python urllib request (отправка запросов с помощью urllib.request в python)

Пояснение: при передаче data со словарём данные кодируются как форма. Для загрузки файлов используется аргумент files.

Проблема: если нужно отправить JSON, но передать data=json.dumps(payload), то заголовок Content-Type не будет установлен. Решение: использовать json или явно задать заголовки.


response = requests.post(url, data=json.dumps(payload), headers={'Content-Type': 'application/json'})

Files upload python (загрузка файлов на сервер с помощью python (requests, flask))

Как обработать ошибки HTTP?

Метод raise_for_status() вызывает исключение HTTPError если статус код 4xx или 5xx.


response = requests.get('https://httpbin.org/status/404')
if response.ok:
    print('Успех')
else:
    print(f'Ошибка {response.status_code}')
# Или с исключением
try:
    response.raise_for_status()
except requests.exceptions.HTTPError as err:
    print(f'HTTP ошибка: {err}')

Python requests method (методы http-запросов в python (get, post, put, delete) с requests)

Пояснение: response.ok возвращает True для кодов 200-399. Исключения удобны для прерывания выполнения при ошибке.

Ошибка: raise_for_status() не вызывается автоматически. Программист должен явно её вызывать.

Как использовать сессии для сохранения состояния?

Объект Session позволяет сохранять куки, заголовки и параметры между запросами.


with requests.Session() as session:
    session.headers.update({'User-Agent': 'my-app'})
    response1 = session.get('https://httpbin.org/cookies/set?name=value')
    response2 = session.get('https://httpbin.org/cookies')
    print(response2.json())  # {'cookies': {'name': 'value'}}

Python request data (извлечение данных из http-запроса (request) в python)

Пояснение: сессия автоматически управляет куками, переданными сервером. Можно задать базовый URL через session.mount или использовать адаптеры.

Проблема: если сессия не закрыта, ресурсы могут не освободиться. Использование менеджера контекста гарантирует закрытие.

Как настроить таймаут и обработку таймаута?

Аргумент timeout задаёт максимальное время ожидания ответа.


try:
    response = requests.get('https://httpbin.org/delay/5', timeout=3)
except requests.exceptions.Timeout:
    print('Запрос превысил время ожидания')

Python send request (отправка http-запроса в python (requests.get/post))

Пояснение: таймаут применяется ко всем операциям (соединение, чтение). Можно задать кортеж (connect_timeout, read_timeout).

Ошибка: отсутствие таймаута может привести к зависанию программы. Рекомендуется всегда указывать таймаут.

Как отправить запрос с аутентификацией?

Для базовой HTTP аутентификации используется аргумент auth.


from requests.auth import HTTPBasicAuth
response = requests.get('https://httpbin.org/basic-auth/user/pass',
                        auth=HTTPBasicAuth('user', 'pass'))
# Сокращенная форма
response = requests.get(url, auth=('user', 'pass'))

Python post file (отправка файла через post-запрос (requests.post(file)) в python)

Пояснение: для Digest аутентификации используется HTTPDigestAuth. Для OAuth2 нужны отдельные библиотеки.

Проблема: пароль может быть виден в коде. Рекомендуется хранить учётные данные в переменных окружения.

Как игнорировать ошибки SSL сертификата?

Установка verify=False отключает проверку SSL (небезопасно).


response = requests.get('https://self-signed.badssl.com/', verify=False)
# Отключение предупреждения
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

Python requests параметры (передача параметров в get/post запросах requests в python)

Пояснение: в production следует использовать собственный сертификат через аргумент verify='/path/to/cert.pem'.

Ошибка: SSLError при невалидном сертификате. Решение: настроить verify или добавить сертификат CA.

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

Прокси задаются через словарь proxies.


proxies = {
    'http': 'http://10.10.1.10:3128',
    'https': 'http://10.10.1.10:1080',
}
response = requests.get('http://example.org', proxies=proxies)
# Для аутентификации на прокси
proxies = {
    'http': 'http://user:pass@10.10.1.10:3128'
}

Пояснение: можно использовать SOCKS прокси, установив pip install requests[socks] и указав socks5://....

Проблема: при использовании прокси без аутентификации может возникать ошибка ConnectionError. Проверьте доступность прокси.

Расширенные примеры использования requests

Потоковая загрузка файлов

Для скачивания больших файлов используется параметр stream=True, чтобы содержимое не загружалось сразу в память.

Пример

import requests

url = 'https://www.example.com/largefile.zip'
response = requests.get(url, stream=True)
response.raise_for_status()
with open('largefile.zip', 'wb') as f:
    for chunk in response.iter_content(chunk_size=8192):
        if chunk:
            f.write(chunk)
Файл largefile.zip сохранен по частям без загрузки в память целиком.

Пояснение: iter_content возвращает итератор по фрагментам ответа. Необходимо обязательно закрывать ответ, но менеджер контекста делает это автоматически.

Повторные попытки при ошибках (Retry)

Используется HTTPAdapter с политикой повторных попыток.

Пример

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

session = requests.Session()
retry = Retry(total=3, backoff_factor=0.5, status_forcelist=[500, 502, 503, 504])
adapter = HTTPAdapter(max_retries=retry)
session.mount('http://', adapter)
session.mount('https://', adapter)

try:
    response = session.get('https://httpbin.org/status/500')
    print(response.status_code)
except requests.exceptions.RetryError:
    print('Все попытки исчерпаны')
После трех попыток выбрасывается RetryError, если сервер продолжает возвращать 500.

Пояснение: backoff_factor определяет задержку между попытками (0.5, 1, 2 секунды). status_forcelist определяет коды, при которых нужно повторить.

Использование собственных заголовков и кук

Можно передать заголовки через аргумент headers и куки через cookies.

Пример

import requests

headers = {
    'User-Agent': 'Mozilla/5.0',
    'Accept': 'application/json'
}
cookies = {'session_id': 'abc123'}
response = requests.get('https://httpbin.org/headers', headers=headers, cookies=cookies)
print(response.json())
{
  "headers": {
    "Accept": "application/json",
    "Cookie": "session_id=abc123",
    "User-Agent": "Mozilla/5.0",
    ...
  }
}

Пояснение: заголовки перезаписывают значения по умолчанию. Куки можно также управлять через session.cookies.

Загрузка файла на сервер с метаданными

Передача файла вместе с дополнительными полями формы.

Пример

import requests

url = 'https://httpbin.org/post'
files = {
    'file': ('report.pdf', open('report.pdf', 'rb'), 'application/pdf'),
    'description': (None, 'Annual report')
}
response = requests.post(url, files=files)
print(response.json())
{
  "files": {"file": "...base64..."},
  "form": {"description": "Annual report"}
}

Пояснение: кортеж может содержать имя файла, тело, MIME-тип и необязательные заголовки. Для полей без файла (None) передаются как обычные данные формы.

Отправка запроса с keep-alive и пулом соединений

По умолчанию requests использует пул соединений. Можно настроить его размер.

Пример

import requests
from requests.adapters import HTTPAdapter

session = requests.Session()
adapter = HTTPAdapter(pool_connections=10, pool_maxsize=20)
session.mount('https://', adapter)
# Все запросы через эту сессию будут использовать пул из 10 соединений
responses = [session.get('https://httpbin.org/get') for _ in range(10)]
Выполнено 10 запросов с переиспользованием TCP соединений.

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

Асинхронные запросы с использованием threading и requests

Для параллельной отправки можно объединить requests с потоками.

Пример

import requests
from concurrent.futures import ThreadPoolExecutor, as_completed

urls = ['https://httpbin.org/delay/1' for _ in range(5)]

def fetch(url):
    return requests.get(url).status_code

with ThreadPoolExecutor(max_workers=5) as executor:
    futures = {executor.submit(fetch, url): url for url in urls}
    for future in as_completed(futures):
        print(future.result())
200
200
200
200
200
(Все запросы выполнены почти одновременно, каждый с задержкой 1 секунда)

Пояснение: ThreadPoolExecutor позволяет отправлять запросы параллельно. Каждый поток имеет собственное соединение. Для большого числа запросов лучше использовать aiohttp или grequests.

Отправка HTTP-запроса в Python (requests.get/post) - comments

En
Python send request (python)