Объект Response в библиотеке Requests представляет собой основной элемент для организации веб-парсинга. Он хранит большое количество информации, полученной от сервера после обработки запроса. Для эффективного и безопасного извлечения данных необходимо уметь работать с доступными методами, свойствами и другими важными особенностями.
При отправке HTTP-запроса с использованием функций requests.get(), requests.post() и т.д., эти функции возвращают объект Response.
import requests # Отправляем GET-запрос r = requests.get('https://api.github.com/events') # Получаем текст ответа print("Содержимое ответа:") print(r.text)
Кодировка
По умолчанию, Requests использует встроенные инструменты для определения кодировки полученного ответа, для этого используется информация из заголовков. Однако предусмотрена возможность узнать, какая кодировка используется и при необходимости изменить ее.
# Узнать текущую кодировку print("Текущая кодировка:", r.encoding) # Изменить кодировку r.encoding = 'ISO-8859-1'
Особенности работы с пользовательскими кодировками
Если в ответ на запрос поступает непонятный набор символов, возможно причина в несоответствии кодировки. Для исправления ситуации можно явно указать данный параметр:
# Используйте необходимую кодировку response.encoding = 'utf-8'
JSON
Для корректной обработки данных в формате JSON в библиотеку requests встроен соответствующий декодер. Пример работы:
import requests response = requests.get(url='https://jsonplaceholder.typicode.com/todos/') print(response.json()) >>> [{'userId': 1, 'id': 1, 'title': 'delectus aut autem', 'completed': False},
В данном случае ответ сервера автоматически преобразуется в список или словарь, в зависимости от структуры JSON. Если процесс декодирования завершить не удается, метод r.json() генерирует исключение requests.exceptions.JSONDecodeError.
Пример с использованием .text
import requests response = requests.get(url='https://jsonplaceholder.typicode.com/todos/') print(response.text) >>>[ { "userId": 1, "id": 1, "title": "delectus aut autem", "completed": false },.....
Если поочередно запустить два последних примера в терминале, окажется что возвращается идентичный ответ. Однако при проверки типа ответа при помощи type() проявятся различия. В случае с .text возвращается тип <class ‘str’>, при использовании .json() – <class ‘list’>.
Стоит отметить, что успешная обработка r.json() не всегда является гарантией, что запрос прошел успешно. В некоторых случаях серверы могут возвращать объект JSON, даже при возникновении ошибки. К примеру, в таком формате может быть прислано описание ошибки 500. Для проверки, был ли запрос успешным, можно использовать метод r.raise_for_status(). Также можно явно проверить код ответа при помощи конструкции: r.status_code==200.
Пример работы:
# Проверка статуса ответа if r.status_code == 200: print("Запрос успешно выполнен") else: print(f"Произошла ошибка: {r.status_code}")
Использование конструкции r.raise_for_status():
try: r.raise_for_status() print("Запрос успешно выполнен") except requests.exceptions.HTTPError as err: print(f"Произошла ошибка: {err}")
Такой запрос позволяет быть уверенным, что полученный ответ будет корректно обработан.
TEXT
Не всегда очевидно, в чем разница подходов, какой лучше использовать. response.json() и response.text обеспечивают получение ответа от сервера, однако они отличаются по типу возвращаемых данных и методам обработки этих данных. Далее этот момент будет рассмотрен подробнее.
response.json()
Возвращает данные в виде списка или словаря, в зависимости от структуры JSON-объекта. Полученные данные автоматически декодируются в Python-объект.
Если строка не является валидным JSON, возвращается исключение JSONDecodeError.
Удобно использовать, когда сервер в качестве ответа использует JSON.
response.text
Данные возвращаются в виде обычной строки. При этом автоматическая обработка данных не предусмотрена, программист должен самостоятельно обработать набор данных.
Используется, когда данные возвращаются в текстовом формате, это может быть JSON, HTML, XML и так далее.
CONTENT
response.content предоставляет ответ сервера в формате байтовой строки. Другими словами, передаются «сырые» байты. Пример:
import requests response = requests.get(url='http://httpbin.org/image/jpeg') print(response.content) >>> b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x02\x00\x1c\x00\x1c\x00\x00\xff\xfe\x005Edited by Paul Sherman for WPClipart, Public Domain\xff\xdb\x00C\x00\x02\x01\x01\x01\x01\x01\x02\x01\x01\x01\x02\x02\x02\x02\x02\x04\x03\x02\x02\x02\x02\x05\x04\x04\x03\x04\x06\x05\x06\x06\x06\x05\x06\x06\x06\x07\t\x08\x06\x07\t\x07\x06\x06\x08\x0b\x08\t\n\n\n\n\n\x06\x08\x0b\x0c\x0b\n\x0c\t\n\n\n\xff\xdb\x00C\x01\x02\x02\x02\x02\x02\x02\x05\x03\x03\x05\n\x07\x06\x07\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\xff\xc0\x00\x11\x08\x00\xb2\x00\xef\x03\x01\x11\x00\x02\x11\x01\x03\x11\x01\xff\xc4\x00\x1e\x00\x00\x01\x05\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x06\x03\x04\x05\x07\x08\x02\t\x00\x01\n\xff\xc4\x00M\x10\x00\x01\x03\x03\x01\x07\x02\x03\x05\x05\x06\x02\x07\x06\x07\x00\x04\x01\x03\x05\x02\x06\x11!\x00\x07\x08\x12\x13\x141#A"$Q\t\x1534a\ ….
Такой вывод не информативен, но в некоторых ситуациях данный вариант вывода предпочтительнее.
Использование менеджера контекста with
Если поставлена задача сохранить данные в файл, что хорошей практикой будет использование менеджера контекста with. В этом случае обеспечивается корректное закрытие и открытие файла, даже если возникнет ошибка:
import requests response = requests.get(url='http://httpbin.org/image/jpeg') with open('image.jpeg', 'wb') as file: file.write(response.content)
Если запустить данный код, в папке проекта появится файл image.jpeg. Флаг «wb» обозначает запись в байтовом формате (write byte).
Стоит учитывать, что в параметр url должна передаваться прямая ссылка на файл. При этом расширение указывать не обязательно.
Когда лучше использовать response.content?
Данный метод оптимально подходит для загрузки различных бинарных файлов (видео, аудио, графику и так далее).
Если необходимо дополнительно обработать «сырые» байты, например, для нестандартного преобразования или декодировки.
Дебаггинг. В некоторых ситуациях необходимо отобразить ответ сервера без предварительной обработки.
Если обобщить информацию выше, то выбор метода получения данных зависит от типа данных и способа их обработки.