🏠 | 💻 IT | Программирование Code | Python |

Работа с REST API в Python

Введение

В этой статье вы узнаете как писать запросы к REST API на Python 3.

Если ваша цель - создание своего REST API - переходите к статье «Flask»

Прежде чем начинать что-то устанавливать рекомендую убедиться, что вы подробно ознакомились с работой в виртуальном окружении Python. Прочитать об этом можно в статье vitualenv

В этой статье подразумевается, что вы работаете в Ubuntu Linux

Содержание статьи
Введение
Подготовка
GET
GET с параметрами
POST
PUT
Аутентификация
Задержка

Подготовка

Активируйте ваше виртуальное окружение и установите requests командой

python3 -m pip install requests

Изучите список установленных модулей

python3 -m pip list

Package Version ---------- --------- certifi 2020.6.20 chardet 3.0.4 idna 2.10 pip 20.2.3 requests 2.24.0 setuptools 50.3.1 urllib3 1.25.10 wheel 0.35.1

requests подтягивает за собой requests, certifi, chardet, idna, urllib3

Проверить куда установился requests в этом окружении можно командой

python3 -m pip show requests

Name: requests Version: 2.24.0 Summary: Python HTTP for Humans. Home-page: https://requests.readthedocs.io Author: Kenneth Reitz Author-email: me@kennethreitz.org License: Apache 2.0 Location: /home/andrei/python/virtualenvs/answerit_env/lib/python3.8/site-packages Requires: certifi, chardet, urllib3, idna Required-by:

GET

Чтобы сделать GET запрос достаточно импортировать requests и выполнить requests.get

Создайте файл rdemo.py следующего содержания:

import requests r = requests.get('https:/xkcd.com/353/') print(r)

Запустите скрипт командой

python3 rdemo.py

<Response [200]>

Если получили 200 значит всё хорошо. Изменим наш код, чтобы узнать, какие действия мы можем произвести с объектом <Response [200]>

dir(r) выдаст список доступных атрибутов и методов

import requests r = requests.get('https:/topbicycle.ru/b/stels_pilot_950_md_26.php') print(dir(r))

['__attrs__', '__bool__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__enter__', '__eq__', '__exit__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__nonzero__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_content', '_content_consumed', '_next', 'apparent_encoding', 'close', 'connection', 'content', 'cookies', 'elapsed', 'encoding', 'headers', 'history', 'is_permanent_redirect', 'is_redirect', 'iter_content', 'iter_lines', 'json', 'links', 'next', 'ok', 'raise_for_status', 'raw', 'reason', 'request', 'status_code', 'text', 'url']

Более подробную информацию можно получить заменив dir(r) на help(r)

Если вам интересно - прочитайте статью requests help

Из этого документа можно узнать http статус содержится в атрибуте status_code

import requests r = requests.get('https:/topbicycle.ru/b/stels_pilot_950_md_26.php') print(r.status_code)

Если всё прошло успешно, то получите

200

ok вернёт True если ответ не 4XX или 5XX

headers возвращает заголовок ответа

Также из этого документа можно узнать что text возвращает содержимое ответа в формате unicode а content содержимое ответа в байтах

Имените код на

import requests r = requests.get('https:/xkcd.com/353/') print("content:") print("-----") print(r.content) print("-----") print("text:") print("-----") print(r.text)

И изучите разницу

Обычно content используют для работы с изображениями

Перейдите на TopBicycle.ru и найдите первое фото велосипеда.

Скопируйте его url

https://topbicycle.ru/b/img/stels_pilot_950_MD_26.jpg

Теперь измените код так, чтобы сохранить изображение в файл

import requests r = requests.get(https://topbicycle.ru/b/img/stels_pilot_950_MD_26.jpg) with open('bike.jpg', 'wb') as f: f.write(r.content)

Если всё прошло успешно, в вашей папке появится следующее фото

stels pilot 950 md 26 в сложенном виде изображение сайта www.TopBicycle.ru
Фото ©: TopBicycle.ru / снято на Samsung

GET с параметрами

Для проверки ваших навыков работы с REST API можно воспользоваться сайтом httpbin.org

Он будет возвращать вам обратно ваш запрос.

Изменим код rdemo.py:

Параметры можно записать сразу после url за знаком вопроса, но надёжнее оформить их в виде отдельного словаря (dictionary).

import requests payload = {'page': 2, 'count': 25} r = requests.get('https://httpbin.org/get', params=payload) print(f"url: {r.url} \n\ntext: \n {r.text}")

python3 rdemo.py

url: https://httpbin.org/get?page=2&count=25 text: { "args": { "count": "25", "page": "2" }, "headers": { "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Host": "httpbin.org", "User-Agent": "python-requests/2.24.0", "X-Amzn-Trace-Id": "Root=1-5f8c2d50-4f48f16c0991ad0e6e45676e" }, "origin": "87.92.8.47", "url": "https://httpbin.org/get?page=2&count=25" }

POST

Чтобы отправить и проверить POST запрос внесите небольшие изменения в код.

Очевидно, что GET нужно заменить на POST, также params нужно заменить на data

import requests payload = {'website': 'heihei.ru', 'established': 2018} r = requests.post('https://httpbin.org/post', data=payload) print(f"url: {r.url} \n\ntext: \n {r.text}")

url: https://httpbin.org/post text: { "args": {}, "data": "", "files": {}, "form": { "established": "2018", "website": "heihei.ru" }, "headers": { "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Content-Length": "34", "Content-Type": "application/x-www-form-urlencoded", "Host": "httpbin.org", "User-Agent": "python-requests/2.24.0", "X-Amzn-Trace-Id": "Root=1-5f8c30ac-6b32899f073f9df4055c55c4" }, "json": null, "origin": "87.92.8.47", "url": "https://httpbin.org/post" }

Ответы, которые мы получили с httpbin приходили в формате json. Для работы c json бывает удобно использовать встроенный метод .json()

В этом случае данные записываются в словарь и к ним очень легко обращаться.

Обратите внимание на "form" данные, которые были переданы возвращаются в этом поле.

Изменим код так, чтобы на экран выводились только эти данные

import requests payload = {'website': 'heihei.ru', 'established': 2018} r = requests.post('https://httpbin.org/post', data=payload) r_dict = r.json() print(r_dict['form'])

python3 rdemo.py

{'established': '2018', 'website': 'heihei.ru'}

PUT

Всё аналогично POST просто замените post на put

Аутентификация

Рассмотрим базовую аутентификацию на сайте httpbin

Придумайте любое имя пользоватлея и пароль к нему.

Я придумал andrey с паролем heihei

Перейдите на httpbin.org . Убедитесь, что в адресной строке стоит basic-auth/andrey/heihei либо те логин и пароль, что придумали вы.

Authentication изображение с сайта www.andreyolegovich.ru
Если Вам нужен новый ноутбук - заходите на сайт Нотик.ру

Введите ваши логин и пароль

Authentication изображение с сайта www.andreyolegovich.ru
Если Вам нужен новый ноутбук - заходите на сайт Нотик.ру

Убедитесь, что аутентификация прошла успешно

Authentication изображение с сайта www.andreyolegovich.ru
Если Вам нужен новый ноутбук - заходите на сайт Нотик.ру

Теперь проделаем такую же аутентификацию с помощью Python

Создайте файл auth_demo.py со следующим кодом

import requests r = requests.get('https://httpbin.org/basic-auth/andrey/heihei', auth=('andrey', 'heihei')) print(r.text)

python3 auth_demo.py

{ "authenticated": true, "user": "andrey" }

Ответ совпадает с тем что мы уже получали в браузере

Выполните такой же запрос, но с неправильным паролем. Убедитесь в том, что text ничего не содержит. Замените print(r.text) на print(r) и убедитесь, что полученный объект это

<Response [401]>

Задержка

Часто бывает нужно ограничить время ожидания ответа. Это можно сделать с помощью параметра timeout

Перейдите на httpbin.org раздел - / #/ Dynamic_data / delete_delay__delay_ и изучите документацию - если делать запрос на этот url можно выставлять время, через которое будет отправлен ответ.

Создайте файл timeout_demo.py следующего содержания

import requests r = requests.get('https://httpbin.org/delay/1', timeout=3) print(r)

Задержка равна одной секунде. А ждать ответ можно до трёх секунд.

python3 tiemout_demo.py

<Response [200]>

Измените код так, чтобы ответ приходил заведомо позже чем наш таймаут в три секунды.

import requests r = requests.get('https://httpbin.org/delay/7', timeout=3) print(r)

Задержка равна семи секундам. А ждать ответ можно по-прежнему только до трёх секунд.

python3 tiemout_demo.py

Traceback (most recent call last): File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 421, in _make_request six.raise_from(e, None) File "<string>", line 3, in raise_from File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 416, in _make_request httplib_response = conn.getresponse() File "/usr/lib/python3.8/http/client.py", line 1347, in getresponse response.begin() File "/usr/lib/python3.8/http/client.py", line 307, in begin version, status, reason = self._read_status() File "/usr/lib/python3.8/http/client.py", line 268, in _read_status line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1") File "/usr/lib/python3.8/socket.py", line 669, in readinto return self._sock.recv_into(b) File "/usr/lib/python3/dist-packages/urllib3/contrib/pyopenssl.py", line 326, in recv_into raise timeout("The read operation timed out") socket.timeout: The read operation timed out During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/usr/lib/python3/dist-packages/requests/adapters.py", line 439, in send resp = conn.urlopen( File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 719, in urlopen retries = retries.increment( File "/usr/lib/python3/dist-packages/urllib3/util/retry.py", line 400, in increment raise six.reraise(type(error), error, _stacktrace) File "/usr/lib/python3/dist-packages/six.py", line 703, in reraise raise value File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 665, in urlopen httplib_response = self._make_request( File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 423, in _make_request self._raise_timeout(err=e, url=url, timeout_value=read_timeout) File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 330, in _raise_timeout raise ReadTimeoutError( urllib3.exceptions.ReadTimeoutError: HTTPSConnectionPool(host='httpbin.org', port=443): Read timed out. (read timeout=3) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "timeout_demo.py", line 4, in <module> r = requests.get('https://httpbin.org/delay/7', timeout=3) File "/usr/lib/python3/dist-packages/requests/api.py", line 75, in get return request('get', url, params=params, **kwargs) File "/usr/lib/python3/dist-packages/requests/api.py", line 60, in request return session.request(method=method, url=url, **kwargs) File "/usr/lib/python3/dist-packages/requests/sessions.py", line 533, in request resp = self.send(prep, **send_kwargs) File "/usr/lib/python3/dist-packages/requests/sessions.py", line 646, in send r = adapter.send(request, **kwargs) File "/usr/lib/python3/dist-packages/requests/adapters.py", line 529, in send raise ReadTimeout(e, request=request) requests.exceptions.ReadTimeout: HTTPSConnectionPool(host='httpbin.org', port=443): Read timed out. (read timeout=3)

Если такая обработка исключений не вызывает у вас восторга - измените код используя try except

import requests try: r = requests.get('https://httpbin.org/delay/7', timeout=3) except (requests.exceptions.Timeout, requests.exceptions.ConnectionError) as err: print('Response is taking too long.') else: print(r)

python3 tiemout_demo.py

Response is taking too long.

Если остались вопросы - смело задавайте их в комментариях.

Поиск по сайту

Контакты и сотрудничество:
Рекомендую наш хостинг beget.ru
Пишите на info@urn.su если Вы:
1. Хотите написать статью для нашего сайта или перевести статью на свой родной язык.
2. Хотите разместить на сайте рекламу, подходящуюю по тематике.
3. Реклама на моём сайте имеет максимальный уровень цензуры. Если Вы увидели рекламный блок недопустимый для просмотра детьми школьного возраста, вызывающий шок или вводящий в заблуждение - пожалуйста свяжитесь с нами по электронной почте
4. Нашли на сайте ошибку, неточности, баг и т.д. ... .......
5. Статьи можно расшарить в соцсетях, нажав на иконку сети: