Python Requests: современное HTTP в несколько строк кода

Пройдите тест, узнайте какой профессии подходите
Сколько вам лет
0%
До 18
От 18 до 24
От 25 до 34
От 35 до 44
От 45 до 49
От 50 до 54
Больше 55

Для кого эта статья:

  • Разработчики, работающие с Python и API
  • Специалисты по автоматизации тестирования и QA-инженеры
  • Ученики и студенты, изучающие программирование и взаимодействие с веб-сервисами

    Когда я впервые столкнулся с необходимостью отправлять HTTP-запросы из Python-скрипта, стандартная библиотека urllib показалась мне излишне сложной и многословной. Всё изменилось, когда я открыл для себя модуль Requests — он произвел революцию в моем подходе к работе с веб-сервисами. Этот инструмент позволяет отправлять HTTP-запросы с элегантной простотой, заворачивая мощный функционал в интуитивно понятный интерфейс. Даже сложные операции, требующие десятков строк с использованием стандартной библиотеки, с Requests выполняются в несколько строк кода. Если вам нужно взаимодействовать с API, парсить веб-страницы или автоматизировать работу с веб-сервисами — этот модуль станет вашим надежным помощником. 🐍

Установка и настройка модуля Requests в Python

Прежде чем погрузиться в мир HTTP-запросов, необходимо правильно установить и настроить модуль Requests. В отличие от многих других библиотек, процесс установки Requests предельно прост и занимает буквально несколько минут.

Начнем с установки. Самый распространенный способ — использование менеджера пакетов pip:

pip install requests

Если вы предпочитаете использовать conda (например, в окружении Anaconda), то команда будет следующей:

conda install -c anaconda requests

После установки рекомендуется проверить корректность процесса. Для этого запустите Python и попробуйте импортировать модуль:

import requests

Если импорт прошел без ошибок, поздравляю — вы готовы к работе! 🎉

Однако перед тем, как начать использовать Requests для отправки HTTP-запросов, стоит обратить внимание на несколько важных аспектов настройки:

  • Виртуальное окружение: Рекомендую устанавливать Requests (как и любые другие сторонние пакеты) в виртуальное окружение Python. Это позволит изолировать зависимости вашего проекта.
  • Версия: Убедитесь, что вы используете актуальную версию. Проверить установленную версию можно с помощью команды pip show requests.
  • SSL-сертификаты: При работе с HTTPS-соединениями важно иметь корректно настроенные сертификаты на вашей системе.

Для удобства сравнения различных методов установки Requests, привожу сводную таблицу:

Метод установки Команда Преимущества Недостатки
pip pip install requests Простота, универсальность, последняя стабильная версия Требует доступа в интернет
conda conda install -c anaconda requests Хорошо работает в экосистеме Anaconda Требует установленной Anaconda
pipenv pipenv install requests Автоматическое управление виртуальным окружением Дополнительная сложность в сравнении с pip
requirements.txt pip install -r requirements.txt Удобно для проектов с несколькими зависимостями Требует подготовки отдельного файла

Михаил Орлов, технический архитектор

Помню случай, когда наша команда разрабатывала систему мониторинга для десятков серверов. Мы столкнулись с проблемой: скрипт, использующий Requests, внезапно перестал работать на одном из серверов. Ошибка была крайне неочевидной – выяснилось, что на проблемном сервере была установлена устаревшая версия библиотеки, которая не поддерживала нужные нам функции.

После этого случая я взял за правило всегда указывать конкретную версию Requests в requirements.txt: requests==2.28.1. Также мы внедрили практику проверки версий всех критических библиотек при запуске системы. Это простое решение сэкономило нам десятки часов на диагностике подобных проблем в будущем.

Пошаговый план для смены профессии

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

Модуль Requests предоставляет интуитивный интерфейс для работы с основными HTTP-методами. Давайте рассмотрим каждый из них подробно, поскольку они формируют фундамент для взаимодействия с веб-ресурсами. 🔄

GET-запросы

GET-запросы используются для получения данных с сервера. Это наиболее часто используемый тип запроса:

Python
Скопировать код
import requests

# Простой GET-запрос
response = requests.get('https://api.github.com/events')

# Проверка статуса ответа
if response.status_code == 200:
print('Успешный запрос!')
# Получаем содержимое ответа в формате JSON
data = response.json()
print(f"Получено {len(data)} событий")
else:
print(f"Ошибка: код {response.status_code}")

POST-запросы

POST-запросы используются для отправки данных на сервер:

Python
Скопировать код
# Отправка данных в формате JSON
payload = {'key1': 'value1', 'key2': 'value2'}
response = requests.post('https://httpbin.org/post', json=payload)

# Отправка данных в формате form-data
response = requests.post('https://httpbin.org/post', data={'key': 'value'})

PUT и DELETE

PUT-запросы обычно используются для обновления существующих ресурсов, а DELETE — для их удаления:

Python
Скопировать код
# PUT-запрос
response = requests.put('https://httpbin.org/put', data={'key': 'updated_value'})

# DELETE-запрос
response = requests.delete('https://httpbin.org/delete')

Другие HTTP-методы

Requests также поддерживает менее распространенные HTTP-методы, такие как PATCH, OPTIONS и HEAD:

Python
Скопировать код
# PATCH-запрос (частичное обновление ресурса)
response = requests.patch('https://httpbin.org/patch', data={'key': 'partial_update'})

# HEAD-запрос (получение только заголовков)
response = requests.head('https://httpbin.org/get')

Для удобства сравнения различных HTTP-методов, рассмотрим следующую таблицу:

HTTP-метод Функция в Requests Типичное применение Идемпотентность
GET requests.get() Получение данных Да
POST requests.post() Создание новых ресурсов Нет
PUT requests.put() Полное обновление ресурсов Да
PATCH requests.patch() Частичное обновление ресурсов Нет
DELETE requests.delete() Удаление ресурсов Да
HEAD requests.head() Получение только заголовков Да
OPTIONS requests.options() Определение возможностей сервера Да

Обработка ответов является критически важной частью работы с HTTP-запросами. Requests предоставляет несколько удобных способов анализа полученных данных:

Python
Скопировать код
response = requests.get('https://api.github.com/events')

# Статус-код ответа
print(response.status_code) # 200

# Содержимое ответа в виде текста
print(response.text)

# Содержимое ответа в виде байтов
print(response.content)

# Автоматическое декодирование JSON
print(response.json())

# Заголовки ответа
print(response.headers)

# Кодировка ответа
print(response.encoding)

При работе с HTTP-запросами важно также правильно обрабатывать ошибки. Модуль Requests предоставляет специальный метод для автоматического вызова исключения в случае ошибки:

Python
Скопировать код
try:
response = requests.get('https://nonexistentwebsite.abc')
response.raise_for_status() # Вызовет исключение при статус-кодах 4xx/5xx
except requests.exceptions.RequestException as err:
print(f"Произошла ошибка: {err}")

Параметры и заголовки запросов: практическое применение

Умение правильно настраивать параметры и заголовки HTTP-запросов — это то, что отличает новичка от профессионала. Грамотное использование этих элементов позволяет существенно расширить возможности вашего кода. 📝

Начнем с URL-параметров. В Requests их можно передавать несколькими способами:

Python
Скопировать код
# Способ 1: Передача параметров через params
payload = {'key1': 'value1', 'key2': 'value2'}
response = requests.get('https://httpbin.org/get', params=payload)
print(response.url) # https://httpbin.org/get?key1=value1&key2=value2

# Способ 2: Передача списка значений
payload = {'key1': 'value1', 'key2': ['value2', 'value3']}
response = requests.get('https://httpbin.org/get', params=payload)
print(response.url) # https://httpbin.org/get?key1=value1&key2=value2&key2=value3

Заголовки запросов играют важнейшую роль при взаимодействии с веб-сервисами. Они могут использоваться для передачи метаданных, аутентификации, указания формата содержимого и многого другого:

Python
Скопировать код
headers = {
'User-Agent': 'Python Requests App',
'Accept': 'application/json',
'Content-Type': 'application/json'
}
response = requests.get('https://api.github.com/events', headers=headers)

Особое внимание стоит уделить заголовку User-Agent. Многие сервисы блокируют или ограничивают запросы с дефолтным User-Agent из Requests:

Python
Скопировать код
# Использование кастомного User-Agent
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'}
response = requests.get('https://www.example.com', headers=headers)

При работе с файлами Requests предоставляет удобный механизм для загрузки:

Python
Скопировать код
files = {'file': ('report.csv', open('report.csv', 'rb'), 'text/csv')}
response = requests.post('https://httpbin.org/post', files=files)

Для обработки куки (cookies) можно использовать как автоматические механизмы, так и ручную настройку:

Python
Скопировать код
# Отправка запроса с куки
cookies = {'session_id': '12345', 'user_id': '54321'}
response = requests.get('https://httpbin.org/cookies', cookies=cookies)

# Получение куки из ответа
cookies_received = response.cookies
print(cookies_received.get_dict())

Анна Соколова, QA-инженер автоматизации

В прошлом году я работала над автоматизацией тестирования REST API крупной платформы онлайн-образования. Мы столкнулись с неожиданной проблемой: наши тесты стабильно проходили на локальных машинах, но регулярно падали на CI-сервере.

После долгих часов отладки мы обнаружили, что проблема заключалась в таймаутах — на CI-сервере сеть была менее стабильной. Решение оказалось простым: добавление параметров timeout и retries в наши запросы:

Python
Скопировать код
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

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

# Теперь все запросы будут автоматически повторяться при ошибках
response = session.get('https://api.example.com/endpoint', timeout=(3.05, 27))

Это небольшое изменение увеличило стабильность наших тестов с 76% до 99.5%. Теперь мы всегда включаем настройку таймаутов и повторов в наши базовые классы для работы с API.

Таймауты и повторные попытки — важнейшие аспекты надежного кода при работе с сетью:

Python
Скопировать код
# Установка таймаута (первое число – таймаут соединения, второе – таймаут чтения)
response = requests.get('https://api.github.com', timeout=(3.05, 27))

# Только общий таймаут
response = requests.get('https://api.github.com', timeout=5)

Вот еще несколько полезных параметров для работы с запросами:

  • stream=True — позволяет загружать большие файлы частями, без загрузки всего содержимого в память
  • verify=False — отключает проверку SSL-сертификата (не рекомендуется для production-кода)
  • allow_redirects=False — отключает автоматическое следование по редиректам
  • proxies — позволяет настроить прокси-сервер для запросов
Python
Скопировать код
# Пример использования прокси
proxies = {
'http': 'http://10.10.1.10:3128',
'https': 'http://10.10.1.10:1080',
}
response = requests.get('https://example.org', proxies=proxies)

# Потоковая загрузка большого файла
response = requests.get('https://example.com/large_file.zip', stream=True)
with open('large_file.zip', 'wb') as f:
for chunk in response.iter_content(chunk_size=8192):
f.write(chunk)

Работа с API: аутентификация и обработка ответов

Взаимодействие с API через модуль Requests — это отдельное искусство, требующее понимания не только самой библиотеки, но и принципов работы с различными механизмами аутентификации. 🔐

Начнем с базовой HTTP-аутентификации, которая остается популярной для многих API:

Python
Скопировать код
# Базовая HTTP-аутентификация
response = requests.get('https://api.github.com/user', auth=('username', 'password'))

# Альтернативный способ
from requests.auth import HTTPBasicAuth
response = requests.get('https://api.github.com/user', auth=HTTPBasicAuth('username', 'password'))

Для работы с более сложными схемами аутентификации, такими как OAuth, Requests также предлагает элегантные решения:

Python
Скопировать код
# OAuth 2.0 аутентификация с использованием токена
headers = {'Authorization': 'Bearer YOUR_ACCESS_TOKEN'}
response = requests.get('https://api.service.com/endpoint', headers=headers)

# Использование OAuth 1.0 аутентификации
from requests_oauthlib import OAuth1
auth = OAuth1('YOUR_APP_KEY', 'YOUR_APP_SECRET',
'USER_OAUTH_TOKEN', 'USER_OAUTH_TOKEN_SECRET')
response = requests.get('https://api.twitter.com/1.1/account/verify_credentials.json', auth=auth)

При работе с API критически важно правильно обрабатывать различные форматы ответов. Requests предоставляет удобные инструменты для работы с наиболее распространенными форматами:

Python
Скопировать код
# Обработка JSON-ответа
response = requests.get('https://api.github.com/events')
json_data = response.json()
for event in json_data:
print(f"Event ID: {event.get('id')}, Type: {event.get('type')}")

# Обработка XML-ответа
response = requests.get('https://www.w3schools.com/xml/note.xml')
import xml.etree.ElementTree as ET
root = ET.fromstring(response.content)
for child in root:
print(f"{child.tag}: {child.text}")

Одним из ключевых аспектов при работе с API является обработка ошибок и статус-кодов. Умение корректно интерпретировать эти сигналы и реагировать на них позволит вашему коду быть более устойчивым:

Python
Скопировать код
response = requests.get('https://api.github.com/repos/invalid/repo')

# Проверка статус-кода
if response.status_code == 200:
print("Успешный запрос")
elif response.status_code == 404:
print("Ресурс не найден")
elif response.status_code == 401:
print("Требуется аутентификация")
elif 500 <= response.status_code < 600:
print("Ошибка на стороне сервера")

Многие API используют пагинацию для возврата больших наборов данных. Вот пример, как можно обработать пагинированные ответы:

Python
Скопировать код
# Обработка пагинации в API GitHub
all_events = []
url = 'https://api.github.com/events'

while url:
response = requests.get(url)
all_events.extend(response.json())

# Проверяем наличие ссылки на следующую страницу в заголовках
if 'next' in response.links.keys():
url = response.links['next']['url']
else:
url = None

print(f"Всего собрано {len(all_events)} событий")

Ограничение скорости запросов (rate limiting) — это еще одна важная тема при работе с API. Многие сервисы ограничивают количество запросов, которые вы можете отправить в определенный период времени:

Python
Скопировать код
import time

# Простая реализация с контролем скорости запросов
for i in range(10):
response = requests.get('https://api.github.com/events')

# Проверяем оставшееся количество запросов
rate_limit_remaining = int(response.headers.get('X-RateLimit-Remaining', 0))

if rate_limit_remaining < 10:
# Если мы почти достигли лимита, делаем паузу
reset_time = int(response.headers.get('X-RateLimit-Reset', 0))
sleep_time = max(reset_time – time.time(), 0) + 1
print(f"Приближаемся к лимиту запросов. Ожидание {sleep_time} секунд...")
time.sleep(sleep_time)

print(f"Запрос {i+1} выполнен, осталось {rate_limit_remaining} запросов")

# Добавляем небольшую задержку между запросами
time.sleep(0.5)

Продвинутые техники использования Sessions в Requests

Использование сессий (Sessions) в Requests — это не просто удобство, а мощный инструмент для оптимизации и контроля HTTP-запросов. Сессии позволяют сохранять определенные параметры между запросами, что особенно полезно при работе с веб-приложениями и API. 🔄

Начнем с базового использования сессий:

Python
Скопировать код
import requests

# Создаем сессию
session = requests.Session()

# Устанавливаем заголовки, которые будут использоваться во всех запросах
session.headers.update({'User-Agent': 'Mozilla/5.0', 'Accept': 'application/json'})

# Выполняем запросы в рамках сессии
response1 = session.get('https://httpbin.org/cookies/set/sessioncookie/123456789')
response2 = session.get('https://httpbin.org/cookies')

# Cookies автоматически сохраняются между запросами
print(response2.json()) # Должен содержать 'sessioncookie': '123456789'

# Закрываем сессию после использования
session.close()

Одним из ключевых преимуществ сессий является улучшение производительности за счет повторного использования соединений:

Python
Скопировать код
# Без использования сессий
for i in range(10):
response = requests.get('https://api.github.com/events')

# С использованием сессий – намного эффективнее
session = requests.Session()
for i in range(10):
response = session.get('https://api.github.com/events')
session.close()

Сессии также позволяют настраивать параметры соединения на более тонком уровне через адаптеры:

Python
Скопировать код
# Настройка пула соединений и повторных попыток
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

# Создаем стратегию повторных попыток
retry_strategy = Retry(
total=3, # максимальное количество повторных попыток
status_forcelist=[429, 500, 502, 503, 504], # коды, при которых повторяем запрос
backoff_factor=1, # фактор экспоненциальной задержки
respect_retry_after_header=True # учитывать заголовок Retry-After
)

# Создаем адаптер с нашей стратегией
adapter = HTTPAdapter(max_retries=retry_strategy, pool_connections=10, pool_maxsize=10)

# Создаем сессию и привязываем адаптер к определенным схемам URL
session = requests.Session()
session.mount("http://", adapter)
session.mount("https://", adapter)

# Теперь все запросы через эту сессию будут использовать настроенный адаптер
response = session.get('https://api.example.com', timeout=5)

Для работы с веб-приложениями часто требуется эмулировать поведение браузера. Сессии в Requests прекрасно подходят для этой задачи:

Python
Скопировать код
# Эмуляция процесса входа в веб-приложение
session = requests.Session()

# Сначала получаем страницу логина, чтобы получить CSRF-токен
login_page = session.get('https://example.com/login')

# Здесь можно использовать библиотеку BeautifulSoup для парсинга HTML
# и извлечения CSRF-токена
import re
csrf_token = re.search('name="csrf_token" value="(.+?)"', login_page.text).group(1)

# Отправляем форму логина
login_data = {
'username': 'myuser',
'password': 'mypassword',
'csrf_token': csrf_token
}
login_response = session.post('https://example.com/login', data=login_data)

# Теперь сессия аутентифицирована, и мы можем получать защищенные страницы
protected_page = session.get('https://example.com/protected')
print('Успешный вход' if 'Welcome, myuser' in protected_page.text else 'Ошибка входа')

Для параллельной обработки множества запросов можно комбинировать сессии с многопоточностью:

Python
Скопировать код
import concurrent.futures
import time

# Функция для выполнения запроса
def fetch_url(session, url):
start = time.time()
response = session.get(url)
return {
'url': url,
'status': response.status_code,
'time': time.time() – start
}

# Список URL для запроса
urls = [
'https://www.python.org',
'https://www.github.com',
'https://www.stackoverflow.com',
'https://www.wikipedia.org',
'https://www.reddit.com'
]

# Создаем сессию с нужными настройками
session = requests.Session()
session.headers.update({'User-Agent': 'Mozilla/5.0'})

# Выполняем запросы параллельно
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
# Создаем набор задач для выполнения
tasks = [executor.submit(fetch_url, session, url) for url in urls]

# Обрабатываем результаты по мере их завершения
for future in concurrent.futures.as_completed(tasks):
result = future.result()
print(f"URL: {result['url']}, Status: {result['status']}, Time: {result['time']:.2f}s")

Иногда требуется сохранить состояние сессии для последующего использования. Для этого можно использовать библиотеку requests-toolbelt:

Python
Скопировать код
from requests_toolbelt.sessions import SessionSerializer

# Создаем и настраиваем сессию
session = requests.Session()
session.get('https://httpbin.org/cookies/set/sessionid/12345')

# Сохраняем состояние сессии
serialized = SessionSerializer().dumps(session)
with open('session.pickle', 'wb') as f:
f.write(serialized)

# В другом месте или в другое время можно восстановить сессию
with open('session.pickle', 'rb') as f:
restored_session = SessionSerializer().loads(f.read())

# Продолжаем использовать восстановленную сессию
response = restored_session.get('https://httpbin.org/cookies')
print(response.json()) # Должен содержать сохраненные cookies

Модуль Requests в Python — это не просто библиотека для отправки HTTP-запросов, это мощный инструмент, который существенно упрощает взаимодействие с веб-сервисами и API. Изучив основные методы, параметры, заголовки запросов, а также механизмы аутентификации и продвинутые техники использования сессий, вы получаете в свое распоряжение полный арсенал средств для разработки эффективных и надежных веб-приложений. Помните, что ключом к успеху является не только знание функциональности модуля, но и понимание HTTP-протокола, а также конкретных особенностей API, с которыми вы работаете. Приобретенные навыки позволят вам создавать код, который не просто работает, а делает это элегантно и эффективно.

Загрузка...