Объект Response в Requests: полное описание
Основной подход к обработке ответа requests
После выполнения запроса библиотека requests возвращает объект Response. Наиболее эффективный способ работы включает следующие шаги:
- Проверка успешности запроса с помощью метода
raise_for_status()или проверка атрибутаok. - Определение типа содержимого по заголовку
Content-Type. - Извлечение данных в нужном формате:
.json(),.text,.content. - Обработка возможных исключений (сетевые ошибки, таймауты, невалидный JSON).
import requests
try:
response = requests.get('https://api.example.com/data')
response.raise_for_status() # вызовет исключение при коде 4xx/5xx
content_type = response.headers.get('Content-Type', '')
if 'application/json' in content_type:
data = response.json()
else:
data = response.text
print(data)
except requests.exceptions.RequestException as e:
print(f'Ошибка запроса: {e}')
Python 2 requests (библиотека requests в python 2)
Возможные проблемы:
- Игнорирование проверки статуса может привести к обработке ошибочного ответа.
- Вызов
.json()на пустом или не JSON ответе вызываетValueError. - Отсутствие таймаута может привести к зависанию скрипта.
Этот универсальный подход подходит для большинства REST API и веб-страниц.
Как получить данные в формате JSON из ответа requests?
Метод response.json() автоматически парсит тело ответа как JSON. Если сервер возвращает некорректный JSON или ответ пуст, будет выброшено исключение ValueError. Рекомендуется оборачивать вызов в try-except.
import requests
resp = requests.get('https://api.github.com/users/octocat')
try:
user = resp.json()
print(user['login'])
except ValueError:
print('Ответ не содержит валидный JSON')Python 3 requests (библиотека requests в python 3)
Типичные ошибки:
- Ошибка парсинга при получении HTML вместо JSON.
- Изменение кодировки: если сервер не указал кодировку, requests использует свою эвристику, что может привести к некорректному парсингу. Рекомендуется устанавливать
response.encodingвручную.
Используется при работе с RESTful API, веб-хуками и любыми сервисами, возвращающими JSON.
Как извлечь текст из ответа requests с корректной кодировкой?
Свойства response.text и response.content дают строку и байты соответственно. text автоматически декодирует, используя предположительную кодировку, но можно явно задать response.encoding = 'utf-8'. Если необходимо получить сырой контент (например, для бинарных данных), используют content.
import requests
r = requests.get('https://www.python.org')
r.encoding = 'utf-8' # принудительно
print(r.text[:200])
Python requests url (выполнение запроса по url с помощью requests в python)
Проблемы:
- Неверная авто-детекция кодировки приводит к кракозябрам (особенно для кириллицы).
- Большие ответы:
textзагружает всё в память, для больших файлов лучше использоватьiter_content.
Применяется для веб-скрапинга, скачивания HTML-страниц, работы с текстовыми API.
Как проверить успешность запроса без исключений?
Атрибут response.ok возвращает True, если код статуса меньше 400. Метод response.raise_for_status() генерирует исключение HTTPError для кодов 400-599. Выбор зависит от стиля: ok для простой проверки, raise_for_status для явной обработки ошибок.
import requests
resp = requests.get('https://httpbin.org/status/404')
if not resp.ok:
print(f'Ошибка: {resp.status_code}')
else:
print(resp.text)Python requests headers (заголовки запросов в python requests)
Ошибка:
- Забывают, что
okпроверяет только коды ниже 400, а для 3xx (редиректы) тожеTrue, еслиallow_redirects=True. - Использование
raise_for_statusбез блока try может прервать выполнение.
Необходимо для валидации ответов перед дальнейшей обработкой.
Как получить HTTP заголовки и куки из ответа requests?
Headerы доступны через response.headers (объект CaseInsensitiveDict). Куки сохраняются в response.cookies (RequestsCookieJar). Можно также получить значение конкретного заголовка: response.headers.get('Content-Type').
import requests
resp = requests.get('https://httpbin.org/cookies/set?name=value')
print(resp.headers['Set-Cookie'])
print(resp.cookies.get('name'))Python requests exceptions (исключения в python requests)
Проблемы:
- Заголовки могут быть неполными (например, отсутствует Content-Length).
- Куки могут быть заблокированы настройками безопасности.
Полезно для отладки, авторизации через куки, отслеживания редиректов.
Как скачать и сохранить бинарный файл (изображение, PDF) из ответа requests?
Для больших файлов использовать response.iter_content(chunk_size=8192) для потоковой загрузки. Для небольших файлов можно использовать response.content и сразу записать в файл. Важно открыть файл в бинарном режиме 'wb'.
import requests
url = 'https://www.python.org/static/img/python-logo.png'
r = requests.get(url, stream=True)
with open('logo.png', 'wb') as f:
for chunk in r.iter_content(chunk_size=1024):
f.write(chunk)Python requests codes (коды ответов http в python requests)
Ошибки:
- Если не указать
stream=True,iter_contentможет загрузить всё в память. - При обрыве соединения файл может быть неполным; рекомендуется проверять размер.
Используется для загрузки контента с сайтов, изображений, документов.
Как получить историю редиректов и отключить их автоматическое следование?
По умолчанию requests следует редиректам (allow_redirects=True). История доступна в response.history (список объектов Response). Чтобы отключить, передать allow_redirects=False.
import requests
r = requests.get('http://httpbin.org/redirect/3')
print(f'Конечный URL: {r.url}')
print(f'Количество редиректов: {len(r.history)}')
for resp in r.history:
print(resp.status_code, resp.url)Python module requests (модуль requests в python)
Проблема:
Неожиданные редиректы могут привести к нежелательному конечному URL или изменению метода (POST -> GET).
Применяется для анализа цепочки перенаправлений или при работе с API, где редиректы недопустимы.
Как корректно обрабатывать исключения при запросах: ConnectionError, Timeout, HTTPError?
Все исключения библиотеки requests наследуются от requests.exceptions.RequestException. Рекомендуется ловить общее исключение или конкретные (Timeout, ConnectionError). Таймаут задаётся параметром timeout.
import requests
from requests.exceptions import Timeout, ConnectionError
try:
r = requests.get('https://httpbin.org/delay/5', timeout=2)
r.raise_for_status()
except Timeout:
print('Превышен таймаут')
except ConnectionError:
print('Не удалось подключиться')
except requests.exceptions.RequestException as e:
print(f'Ошибка: {e}')
Типичные ошибки:
- Отсутствие таймаута может привести к зависанию скрипта на неопределённое время.
- Игнорирование ConnectionError при нестабильной сети.
Необходимо для стабильной работы программ, особенно при периодических опросах серверов.
Ниже приведены расширенные примеры, демонстрирующие различные аспекты обработки ответа requests в реальных сценариях.
Пример 1. Получение JSON с GitHub API с обработкой пагинации
Запрос списка репозиториев пользователя, обработка заголовка Link для перехода по страницам.
import requests
import json
def get_all_repos(username):
repos = []
url = f'https://api.github.com/users/{username}/repos?per_page=100'
while url:
resp = requests.get(url)
resp.raise_for_status()
repos.extend(resp.json())
link = resp.links.get('next', {}).get('url')
url = link
return repos
repos = get_all_repos('octocat')
print(f'Найдено {len(repos)} репозиториев')
for repo in repos[:3]:
print(repo['name'])
Найдено 8 репозиториев Hello-World Spoon-Knife octocat.github.com
Пример 2. Потоковая загрузка большого файла с индикацией прогресса
import requests
url = 'https://speed.hetzner.de/1GB.bin'
resp = requests.get(url, stream=True)
total = int(resp.headers.get('content-length', 0))
downloaded = 0
with open('test.bin', 'wb') as f:
for chunk in resp.iter_content(chunk_size=8192):
if chunk:
f.write(chunk)
downloaded += len(chunk)
percent = 100 * downloaded / total if total else 0
print(f'Downloaded {downloaded} of {total} bytes ({percent:.1f}%)')
print('Download complete')
Downloaded 1048576 of 1073741824 bytes (0.1%) ... Downloaded 1073741824 of 1073741824 bytes (100.0%) Download complete
Пример 3. Работа с сессией и куками: авторизация и сохранение состояния
import requests
session = requests.Session()
login_data = {'username': 'user', 'password': 'pass'}
session.post('https://httpbin.org/post', data=login_data)
resp = session.get('https://httpbin.org/cookies')
print(resp.json())
{'cookies': {'session': 'abc123'}}