Как выполнять HTTP запросы в Python: обзор инструментов

Раздел: Сетевые технологии -> Взаимодействие с веб-ресурсами

Основной подход: библиотека requests

Библиотека requests предоставляет высокоуровневый интерфейс для HTTP запросов. Она проще в использовании по сравнению с urllib и поддерживает все основные методы: GET, POST, PUT, DELETE и другие. Для начала работы необходимо установить библиотеку: pip install requests.

import requests

response = requests.get('https://api.example.com/data')
print(response.status_code)
print(response.json())

Python urls (работа с url в python (requests))

В этом примере выполняется GET запрос, проверяется статус ответа и извлекаются данные в формате JSON. Библиотека автоматически обрабатывает кодировку, заголовки и cookies.

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

  • Ошибка соединения (ConnectionError) - если сервер недоступен.
  • Таймаут (Timeout) - если ответ не получен вовремя. Рекомендуется всегда задавать таймауты: requests.get(url, timeout=5).
  • HTTP ошибки (404, 500) - статус коды можно проверять через response.raise_for_status().

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

params = {'key1': 'value1', 'key2': 'value2'}
response = requests.get('https://httpbin.org/get', params=params)
print(response.url)  # https://httpbin.org/get?key1=value1&key2=value2

Параметры автоматически кодируются и добавляются к URL.

Проблема: если параметры содержат специальные символы, requests их URL-кодирует, но иногда нужно избежать двойного кодирования. Используйте params с готовыми строками.

Как отправить POST запрос с данными формы?

data = {'username': 'user', 'password': 'pass'}
response = requests.post('https://httpbin.org/post', data=data)
print(response.json())

Данные формы автоматически кодируются в application/x-www-form-urlencoded.

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

import json
payload = {'key': 'value'}
response = requests.post('https://httpbin.org/post', json=payload)
print(response.json())

Библиотека автоматически устанавливает заголовок Content-Type: application/json.

Ошибка: если передать словарь в data вместо json, данные будут отправлены как форма, а не как JSON.

Как работать с сессиями и поддерживать cookies?

session = requests.Session()
session.get('https://httpbin.org/cookies/set?name=value')
response = session.get('https://httpbin.org/cookies')
print(response.json())  # cookies сохраняются между запросами

Сессии также используют пул соединений для повышения производительности.

Проблема: cookies могут не сохраняться, если сервер использует HttpOnly или Secure флаги, но requests их обрабатывает.

Как установить пользовательские заголовки?

headers = {'User-Agent': 'MyApp/1.0'}
response = requests.get('https://httpbin.org/headers', headers=headers)
print(response.json())

Вариант: библиотека urllib (стандартная библиотека)

Модуль urllib.request позволяет выполнять HTTP запросы без сторонних зависимостей. Однако требует больше ручной работы.

Как сделать GET запрос с помощью urllib?

from urllib.request import urlopen
response = urlopen('https://api.example.com/data')
print(response.status)
data = response.read().decode('utf-8')

Ответ нужно декодировать вручную. Для JSON потребуется дополнительно импортировать json.

Ошибки: Необходимо обрабатывать исключения (URLError, HTTPError). Нет автоматического таймаута.

Как сделать POST запрос с данными?

import urllib.request
import urllib.parse

data = urllib.parse.urlencode({'key': 'value'}).encode('utf-8')
req = urllib.request.Request('https://httpbin.org/post', data=data)
response = urllib.request.urlopen(req)
print(response.read().decode())

Данные кодируются вручную.

Проблема: нет автоматического управления cookies, требуется использовать HTTPCookieProcessor.

Вариант: библиотека httpx

httpx - современная библиотека с поддержкой синхронного и асинхронного режимов, HTTP/2.

Как сделать GET запрос с httpx?

import httpx
response = httpx.get('https://httpbin.org/get')
print(response.status_code)
print(response.json())

Интерфейс похож на requests, но добавлена поддержка HTTP/2 и асинхронных вызовов.

Ошибка: httpx требует установки отдельно (pip install httpx). Для HTTP/2 нужен дополнительный пакет pip install httpx[http2].

Вариант: библиотека aiohttp (асинхронная)

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

Как выполнить асинхронный GET запрос?

import aiohttp
import asyncio

async def fetch():
    async with aiohttp.ClientSession() as session:
        async with session.get('https://httpbin.org/get') as response:
            return await response.json()

result = asyncio.run(fetch())
print(result)

Требуется понимание асинхронного программирования.

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

Расширенные примеры работы с URL в Python

1. Обработка параметров с кодировкой специальных символов

Пример
import requests

params = {'q': 'python requests+urllib', 'page': 1}
response = requests.get('https://httpbin.org/get', params=params)
print('URL:', response.url)
# Вывод: URL: https://httpbin.org/get?q=python+requests%2Burllib&page=1
# Результат:
URL: https://httpbin.org/get?q=python+requests%2Burllib&page=1

Параметры автоматически URL-кодируются. Знак '+' кодируется как %2B, пробел как +.

2. Загрузка файлов с сервера

Пример
import requests

url = 'https://www.python.org/static/img/python-logo.png'
response = requests.get(url)
if response.status_code == 200:
    with open('python-logo.png', 'wb') as f:
        f.write(response.content)
    print('File downloaded successfully')
else:
    print('Failed to download')

Используется атрибут response.content для бинарных данных.

3. Отправка файлов на сервер (multipart/form-data)

Пример
import requests

files = {'file': ('test.txt', b'Hello, world!', 'text/plain')}
response = requests.post('https://httpbin.org/post', files=files)
print(response.json())
# Результат (часть ответа):
{
  "files": {"file": "Hello, world!"},
  ...
}

Второй элемент кортежа - имя файла, третий - MIME тип (опционально).

4. Использование прокси-сервера

Пример
import requests

proxies = {
    'http': 'http://user:pass@proxy.example.com:8080',
    'https': 'https://user:pass@proxy.example.com:8080'
}
response = requests.get('https://httpbin.org/ip', proxies=proxies)
print(response.json())

Прокси указываются отдельно для http и https. Требуется аутентификация, если нужна.

5. Работа с таймаутами и повторными попытками

Пример
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry
import requests

session = requests.Session()
retry = Retry(total=3, backoff_factor=1, 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', timeout=5)
    print(response.status_code)
except requests.exceptions.RetryError as e:
    print('Max retries exceeded:', e)

Настройка повторных попыток с экспоненциальной задержкой.

6. Аутентификация (Basic и Digest)

Пример
import requests
from requests.auth import HTTPBasicAuth, HTTPDigestAuth

# Basic аутентификация
response = requests.get('https://httpbin.org/basic-auth/user/pass',
                        auth=HTTPBasicAuth('user', 'pass'))
print(response.status_code)  # 200

# Digest аутентификация
response = requests.get('https://httpbin.org/digest-auth/auth/user/pass',
                        auth=HTTPDigestAuth('user', 'pass'))
print(response.status_code)  # 200

7. Использование cookies из браузера (пример с requests)

Пример
import requests

url = 'https://example.com'
cookies = {'sessionid': 'abc123'}
response = requests.get(url, cookies=cookies)
print(response.cookies)  # также можно получить cookies из ответа

8. Работа с URL с помощью urllib.parse

Пример
from urllib.parse import urlparse, urlencode, urljoin, quote, unquote

# Разбор URL
parsed = urlparse('https://user:pass@example.com:8080/path?query=1#frag')
print('Scheme:', parsed.scheme)
print('Netloc:', parsed.netloc)
print('Path:', parsed.path)
print('Query:', parsed.query)
print('Fragment:', parsed.fragment)

# Кодирование строки
encoded = quote('привет мир')
print('Encoded:', encoded)  # %D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82%20%D0%BC%D0%B8%D1%80

# Декодирование
decoded = unquote(encoded)
print('Decoded:', decoded)

# Объединение URL
base = 'https://example.com/api/v2/'
relative = '../users'
full_url = urljoin(base, relative)
print('Joined URL:', full_url)  # https://example.com/api/users

Модуль urllib.parse полезен для манипуляций с URL.

9. Асинхронные запросы с aiohttp (загрузка нескольких ресурсов параллельно)

Пример
import aiohttp
import asyncio

async def fetch(session, url):
    async with session.get(url) as response:
        return await response.text()

async def main():
    urls = [
        'https://httpbin.org/delay/1',
        'https://httpbin.org/delay/2',
        'https://httpbin.org/delay/3'
    ]
    async with aiohttp.ClientSession() as session:
        tasks = [fetch(session, url) for url in urls]
        results = await asyncio.gather(*tasks)
        for i, result in enumerate(results):
            print(f'{i}: length = {len(result)}')

asyncio.run(main())

Все запросы выполняются параллельно. Время выполнения минимально.

10. Отправка запроса с кастомным SSL сертификатом

Пример
import requests

response = requests.get('https://self-signed.badssl.com/', verify=False)
# Или указать путь к сертификату:
# response = requests.get('https://example.com', verify='/path/to/cert.pem')
print(response.status_code)

Использование verify=False отключает проверку SSL (не рекомендуется в production).

Работа с URL в Python (requests) - comments

En
Python urls (python)