Библиотека requests – это продвинутый инструмент для создания HTTP-запросов в Python. Легкий для понимания и аккуратный API делает процесс создания запросов значительно проще. Поэтому можно сосредоточиться на взаимодействии со службами и использовании данных в программе.
Сегодня попробуем подробно разобрать основные аспекты работы с этой библиотекой. Конечно, все рассмотреть не получится, потому что тема слишком обширная. Но понять основы вы сможете.
В частности, сегодня разберем следующие темы:
- Создание запросов, используя наиболее популярные HTTP-методы.
- Внесение изменений в заголовки запросов и данных с помощью строки запроса и содержимого сообщения.
- Анализ данных запросов и откликов.
- Создание авторизированных запросов.
- Настройка запросов, чтобы не допустить ошибки и замедление работы программы.
Несмотря на то, что информация представлена в доступной форме, необходимо владеть, по крайней мере, базовыми аспектами работы с HTTP.
Что такое HTTP-запрос?
HTTP – один из самых распространенных протоколов в интернете. Он появился в начале 90-х, и даже сейчас является обязательным элементом процесса загрузки и отображения веб-страниц. Создавался в качестве стандарта, с помощью которого можно передавать гипертекст.
Название протокола – это аббревиатура, которая расшифровывается, как HyperText Transfer Protocol, что и переводится, как протокол, созданный для передачи гипертекста. Простыми словами, таких файлов, в которых содержатся ссылки на другие документы. Типичным примером гипертекста являются классические веб-страницы.
А запрос – это обращение, в процессе которого клиент хочет получить от сервера определенные данные.
Самый простой вариант, как можно разобраться с HTTP-протоколом – это непосредственно обратиться к какому-то серверу. После каждого обращения возвращается определенный код, который демонстрирует статус обращения. Это могут быть такие статусы, как:
- Страница не найдена.
- Страница успешно загружена.
- Нет данных.
- Вход запрещен.
Перечень статусов очень большой. Теперь, после небольшого ликбеза можно приступать к тому, как с этими запросами работать.
Как установить библиотеку?
Сначала необходимо установить библиотеку requests. Чтобы это сделать, надо ввести следующую команду.
$ pip install requests
Если же вы хотите использовать виртуальную среду Pipenv, то для работы с пакетами Python надо воспользоваться другой командой.
$ pipenv install requests
Непосредственно после установки requests становится доступным для использования. Импорт библиотеки осуществляется так.
import requests
Вот уже и получилось завершить все подготовительные работы. А начинать обучение библиотеке наиболее удобно с GET-запроса.
Метод GET библиотеки
Такие HTTP-методы, как GET и POST определяют действия, которые будут выполняться при создании HTTP-запроса. Кроме GET и POST также можно воспользоваться некоторыми другими методами для достижения поставленной цели. В этой статье они будут рассмотрены далее.
GET-это один из методов, который пользуется самой высокой популярностью. Он говорит о том, что осуществляется попытка получить информацию с определенного сервера. Для выполнения этого запроса необходимо воспользоваться командой requests.get().
Мы выполним запрос GET по поводу Root REST API на GitHub, чтобы проверить, как эта команда работает. Работает все следующим образом.
requests.get('https://api.github.com') <Response [200]>
Мы вызвали метод get() для URL, который указан в первой строчке вышеприведенного кода.
Если в результате его выполнения не появилось никаких ошибок, это говорит о том, что у нас получилось выполнить первый запрос. Затем проанализируем ответ на запрос, который мы отправили ранее. Чтобы его получить, требуется Response.
Получение данных в качестве ответа
Response – это достаточно функциональный объект, с помощью которого можно анализировать результаты запроса. Как пример,покажем прошлый запрос, только теперь результат будет приведен в форме переменной.
Следовательно, будет проще лучше понять его особенности применения.
response = requests.get('https://api.github.com')
В этом примере с использованием get() захватывается конкретное число, которое является элементом Response, и размещается в переменной, которая так и называется. После этого мы можем использовать эту переменную, чтобы проанализировать данные, полученные нами на предыдущем этапе.
HTTP-коды
Первые сведения, которые будут получены с использованием библиотеки Response – это коды состояния. Они сообщают о статусе запроса, который передается.
Так, код 200 ОК говорит о том, что при выполнении запроса проблем не возникало. А вот если возвращается код 404, это указывает на то, что интересующий ресурс не был обнаружен. Есть большое количество других кодов, способных сообщать важные сведения, связанные с запросом.
С помощью.status_code можно увидеть код состояния, который возвращается от сервера.
>>> response.status_code 200
В этом примере был возвращен код 200. Это указывает на то, что при выполнении запроса проблем не было. А сервер ответил, отобразив запрашиваемую информацию.
В ряде случаев необходимо использовать полученные данные для создания кода приложения.
if response.status_code == 200: print('Success!') elif response.status_code == 404: print('Not Found.')
Здесь, если с сервера будет получен код 200, то приложение выведет Success!. Тем не менее, если код будет 404, то тогда появится Not Found.
Вообще, весь этот процесс можно сделать значительно проще благодаря requests. Если использовать Response в условных выражениях, то при получении кода между 200 и 400 будет отображаться True. Иначе ответ будет False.
То есть, последний пример можно сделать значительно проще благодаря оператору if.
Python if response: print('Success!') else: print('An error has occurred.')
Необходимо учитывать то, что этот метод не проверяет, имеет ли статусный код точное значение 200. Все потому, что все коды между 200 и 400 считаются успешными. Например, 204 NO CONTENT и 304 NOT MODIFIED считаются успешными в случае, если они способны предоставить действительный ответ.
Например, код 204 указывает на то, что ответ благополучно получен. Тем не менее, содержимое отсутствует. Простыми словами, для рационального использования этого метода надо удостовериться, что изначальный запрос был сделан. Надо найти код состояния, и, если появляется необходимость, внести соответствующие коррективы. Естественно, зависящие от значения кода, который был получен.
Например, если с помощью if вы не желаете выполнять проверку кода, характеризующего запрос, можно диапазон исключений сделать шире для тех результатов, выполнение которых обернулось неудачей. Это делается с помощью .raise_for_status().
import requests from requests.exceptions import HTTPError for url in ['https://api.github.com', 'https://api.github.com/invalid']: try: response = requests.get(url) # если ответ успешен, исключения задействованы не будут response.raise_for_status() except HTTPError as http_err: print(f'HTTP error occurred: {http_err}') # Python 3.6 except Exception as err: print(f'Other error occurred: {err}') # Python 3.6 else: print('Success!')
Если этот метод используется для вызова исключений, то к ряду кодов состояния применяется HTTPError. Когда код говорит о том, что запрос выполнен без каких-либо проблем, то исключения отсутствуют.
Чтобы сделать работу в Python эффективнее, рекомендуется изучить f-строки. Настоятельно рекомендуется ими пользоваться, поскольку это превосходный вариант, как сделать форматирование проще.
Изучение вариантов кодов, которые были получены с сервера, – это превосходный старт для изучения requests. При этом, при создании GET-запроса значение кода – не самая важная информация, которую хотел бы получить разработчик. Как правило, запрос выполняется для получения содержательной информации. Дальше мы покажем, как добраться до актуальных данных, которые сервер отправляет в ответ на запрос, отправленный пользователем.
Получение контента, который есть на странице
Очень часто в ответе на запрос GET содержится довольно полезная информация. Она находится в теле сообщения и называется пейлоад. С помощью атрибутов и методов библиотеки Response, можно получить пейлоад в разных форматах.
Для получения содержимого запроса в байтах, используется .content.
>>> response = requests.get('https://api.github.com') >>> response.content b'{"current_user_url":"https://api.github.com/user","current_user_authorizations_html_url":"https://github.com/settings/connections/applications{/client_id}","authorizations_url":"https://api.github.com/authorizations","code_search_url":"https://api.github.com/search/code?q={query}{&page,per_page,sort,order}","commit_search_url":"https://api.github.com/search/commits?q={query}{&page,per_page,sort,order}","emails_url":"https://api.github.com/user/emails","emojis_url":"https://api.github.com/emojis","events_url":"https://api.github.com/events","feeds_url":"https://api.github.com/feeds","followers_url":"https://api.github.com/user/followers","following_url":"https://api.github.com/user/following{/target}","gists_url":"https://api.github.com/gists{/gist_id}","hub_url":"https://api.github.com/hub","issue_search_url":"https://api.github.com/search/issues?q={query}{&page,per_page,sort,order}","issues_url":"https://api.github.com/issues","keys_url":"https://api.github.com/user/keys","notifications_url":"https://api.github.com/notifications","organization_repositories_url":"https://api.github.com/orgs/{org}/repos{?type,page,per_page,sort}","organization_url":"https://api.github.com/orgs/{org}","public_gists_url":"https://api.github.com/gists/public","rate_limit_url":"https://api.github.com/rate_limit","repository_url":"https://api.github.com/repos/{owner}/{repo}","repository_search_url":"https://api.github.com/search/repositories?q={query}{&page,per_page,sort,order}","current_user_repositories_url":"https://api.github.com/user/repos{?type,page,per_page,sort}","starred_url":"https://api.github.com/user/starred{/owner}{/repo}","starred_gists_url":"https://api.github.com/gists/starred","team_url":"https://api.github.com/teams","user_url":"https://api.github.com/users/{user}","user_organizations_url":"https://api.github.com/user/orgs","user_repositories_url":"https://api.github.com/users/{user}/repos{?type,page,per_page,sort}","user_search_url":"https://api.github.com/search/users?q={query}{&page,per_page,sort,order}"}'
Использование .content гарантирует доступ к чистым байтам ответного пейлоада. Простыми словами, ко всей информации, которая находится в теле запроса, который отправляется клиентским приложением. Тем не менее, нередко появляется необходимость выполнять конвертирование полученных данных в строку в кодировке UTF-8. Чтобы это сделать в response, требуется воспользоваться методом .text.
>>> response.text
Декодирование байтов в данные строчного формата требует наличия определенной модели кодировки. По умолчанию, requests попытается узнать текущую кодировку, учитывая заголовки HTTP. Чтобы указать требуемую кодировку, необходимо перед .text указать .encoding.
>>> response.encoding = 'utf-8' # Optional: requests infers this internally >>> response.text
Если проанализировать ответ, можно увидеть, что его содержимое является сериализованным JSON-контентом. С помощью словаря, можно взять полученные из .text строки и выполнить с ними обратную сериализацию с помощью json.loads() Есть и более простой метод, который требует использования .json().
>>> response.json()
Тип полученного значения .json() – это словарь. Проще говоря, чтобы получить определенные данные, необходимо знать ключ.
Коды состояния и тело сообщения предоставляют широкий диапазон возможностей. Тем не менее, для их грамотного применения надо понять, что такое метаданные и HTTP-заголовки.
HTTP-заголовки
Чтобы просматривать HTTP-заголовки, необходимо заглянуть в атрибут .headers.
>>> response.headers
Этим методом возвращается словарь. Это дает возможность получить доступ к значению HTTP-заголовка, владея ключом. Так, для просмотра типа контента необходимо использовать Content-Type.
>>> response.headers['Content-Type']
У объектов словарей есть свои особенности. Специфика HTTP в том, что заголовки не чувствительны к регистру. Это означает, что при получении доступа к заголовкам можно не волноваться по поводу строчных или прописных букв.
>>> response.headers['content-type']
Requests параметры запроса
Самым легким вариантом действий, как настраивать GET-запрос, является передача значений через параметры строки запроса в URL.
При использовании метода get(), данные передаются в params. А для просмотра библиотеки requests можно использовать Search API на GitHub.
import requests # Поиск местонахождения для запросов на GitHub response = requests.get( 'https://api.github.com/search/repositories', params={'q': 'requests+language:python'}, ) # Анализ некоторых атрибутов местонахождения запросов json_response = response.json() repository = json_response['items'][0] print(f'Repository name: {repository["name"]}') # Python 3.6+ print(f'Repository description: {repository["description"]}') # Python 3.6+
Когда передается словарь {‘q’: ‘requests+language:python’} в параметр params, который является частью .get(), можно изменить ответ, что был получен при использовании Search API.
Можно передать параметры в get() в форме словаря, как было показано выше. Также можно использовать список кортежей.
Python >>> requests.get( ... 'https://api.github.com/search/repositories', ... params=[('q', 'requests+language:python')], ... ) <Response [200]> Помимо этого, возможно передавать значение и в байтовом формате. >>> requests.get( ... 'https://api.github.com/search/repositories', ... params=b'q=requests+language:python', ... ) <Response [200]>
Строки запроса полезно использовать, если надо уточнить параметры в GET-запросах. Помимо этого, можно настроить запросы с помощью добавления либо изменения заголовков отправленных сообщений.
Заключение
Мы рассмотрели базовые аспекты работы с HTTP-запросами в Python. В частности, мы рассмотрели, как установить библиотеку, методы GET, Request, Response, HTTP-коды и ряд других похожих тем. Конечно, это не все. Но мы и не собираемся останавливаться. Во второй части мы обязательно продолжим рассматривать эту тему.
Далее будут рассмотрены такие вопросы, как настройка HTTP-заголовка запроса, будут приведены примеры HTTP-методов, тело сообщения, анализ запроса, проверка сертификата безопасности. Также будут рассмотрены другие темы, связанные с HTTP-запросами.