Перейдите к следующему слайду, нажав кнопку Вправо
Учимся работать с библиотекой requests в Python
Подготовлено онлайн-курсом
import requests
url = 'https://yandex.ru'
requests.get(url)
requests.get
Шлёт запрос на Яндекс как будто мы просто зашли из браузера
import requests
url = 'https://yandex.ru'
response = requests.get(url)
requests.get
Не просто послали запрос, а поймали ответ в переменную
>>> response.status_code
200
>>> response.ok
True
HTTP статус ответа
Как узнать статус ответа
200 — код ответа. Есть много разных кодов ответа. Вы уже наверняка знаете про 404 — "страница не найдена", это неудавшийся запрос. Ответ 200 — успешный.
Успешен любой ответ, начинающийся с двойки — 2xx.
response.ok — проверка на успешность
Подробнее читайте по ссылке.
>>> response.raise_for_status()
requests.exceptions.HTTPError ....
Стандартная проверка статуса
Как проверить ответ сервера
Метод raise_for_status выкинет исключение (HTTPError), если запрос к серверу завершился неудачно. То есть если у запроса статус 4xx (ошибка клиента) или 5xx (ошибка сервера).
Эквивалентный код:
>>> if not response.ok:
... raise requests.exceptions.HTTPError(response=response)
requests.exceptions.HTTPError ....
>>> response.encoding
'utf-8'
>>> response.url
'https://yandex.ru'
>>> response.is_redirect
False
response
В ответе хранится много всего полезного
payload = {"text": "python"}
response = requests.get('https://yandex.ru', params=payload)
response.raise_for_status()
>>> response.url
'https://yandex.ru/?text=python'
params
Формирование запросов с параметрами
делаем запрос с параметрами, получаем ответ
адрес, на который библиотека отправила запрос
payload = {"q": ""}
response = requests.get('https://yandex.ru', params=payload)
response.raise_for_status()
>>> response.url
'https://yandex.ru/?q='
params - ключ без значения
делаем запрос с параметром без значения, получаем ответ
этот адрес аналогичен такому: https://yandex.ru/?q
payload = {"text": "python django"}
response = requests.get('https://yandex.ru', params=payload)
response.raise_for_status()
>>> response.url
'https://yandex.ru/?text=python+django'
Экранирование ссылок
Пробелы в параметре преобразуются в плюсы
делаем запрос с параметрами, получаем ответ
адрес, на который библиотека отправила запрос
response = requests.get('https://www.ibm.com/developerworks/topics/django python')
response.raise_for_status()
>>> response.url
'https://www.ibm.com/developerworks/topics/django%20python'
Экранирование ссылок
Пробелы в ссылке преобразуются в %20
делаем запрос, получаем ответ
в адресе нет пробела, библиотека заменила его на %20
response = requests.get('https://ru.wikipedia.org/wiki/django rest framework')
response.raise_for_status()
>>> response.url
'https://ru.wikipedia.org/wiki/django-rest-framework'
Экранирование ссылок
Многие сайты самостоятельно преобразуют пробелы в дефисы или нижние подчёркивания
делаем запрос
сайт перенаправил запрос на другой адрес
payload = {"text": "курсы веб-разработки python"}
response = requests.get('https://yandex.ru', params=payload)
response.raise_for_status()
>>> response.url
'https://yandex.ru/?text=%D0%BA%D1%83%D1%80%D1%81
%D1%8B+%D0%B2%D0%B5%D0%B1-%D1%80%D0%B0%D0%B7%D1%80
%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B8+python'
Экранирование ссылок
Кириллица может выглядеть странно, когда она закодирована для url запроса. Не пугайтесь, если встретитесь с таким.
делаем запрос с параметрами, получаем ответ
Адрес, на который библиотека отправила запрос
>>> response.text
'Weather report: Moscow, Russia
Overcast
\ / Переменная облачность
_ /"".-. -21--19 °C
\_( ). ↖ 4 km/h
/(___(__) 20 km
0.0 mm'
>>> response.raw
<urllib3.response.HTTPResponse object at 0x7f59da492a58>
>>> response.content
b'Weather report: Moscow, Russia
Overcast\n \x1b[38;5;240;1m .--.
\x1b[0m \x1b[38;5;049m2\x1b[0m-\x1b[38;
\x94\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94
\x80\xe2\x94\x80\xe2\x94\x80\xe2\x94\x80
Содержимое ответа
Чаще всего вам нужен текст, но бывают и исключения
Текст в юникоде
Текст в byte формате
Ответ в "сыром" виде
>>> response.text
'{ "user_id" : "123132421" }'
>>> response.json()
{ "user_id" : "123132421" }
String vs JSON
Обратите внимание на возвращаемый тип
Строка с словарём
Словарь
>>> response.status_code
200
>>> response.text
"Ошибка 500"
Иногда status 200, но ошибка в ответе
Некоторые сайты всегда отправляют 200, но в тексте ответа присылают код ошибки.
import requests
url = 'https://yandex.ru'
response = requests.post(url)
response.raise_for_status()
requests.post
А вот так шлётся POST запрос
url = 'https://gist.github.com/статья'
payload = {
"new-text": "Теперь в этой статье написан этот текст"
}
response_get = requests.get(url)
response_get.raise_for_status()
response_post = requests.post(url, data=payload)
response_post.raise_for_status()
# response_get.text - выдаст статью, которую вы хотели.
# response_post.text - выдаст ту же статью, но уже отредактированную.
POST data
Разница между GET запросом и POST запросом в том, что у POST есть тело запроса.
GET запрос
POST запрос
Тело POST запроса
Зачем нужен POST запрос
url = 'https://passport.yandex.ru/auth'
payload = {
"login": "some-login",
"password": "sample-text"
}
response = requests.post(url, json=payload)
response.raise_for_status()
print(response.json())
POST JSON data
Можно отправлять данные в формате JSON и смотреть ответы в формате JSON
{"account_status": "created"}
url = 'https://wikipedia.com'
headers = {
'User-Agent': 'curl',
'Accept-Language': 'ru-RU'
}
response = requests.get(url, headers=headers)
response.raise_for_status()
HTTP headers (Заголовки)
Так можно самостоятельно менять заголовки запроса
Заголовки запроса
url = 'https://wikipedia.com'
headers = {
"Authorization": "Bearer cn389ncoiwuencr"
}
response = requests.get(url, headers=headers)
response.raise_for_status()
OAuth 2.0 bearer tokens (Заголовок авторизации)
Пример авторизации с токеном в заголовке запроса
import requests
filename = 'dvmn.svg'
url = "https://dvmn.org/filer/canonical/1542890876/16/"
response = requests.get(url)
response.raise_for_status()
with open(filename, 'wb') as file:
file.write(response.content)
Как скачать картинку
Пример скачивания картинки
import requests
with open('image.jpg', 'rb') as file:
url = '...'
files = {
'media': file,
}
response = requests.post(url, files=files)
response.raise_for_status()
Как отправить картинку
Пример отправки картинки на сервер
Название media взято из документации к API
import requests
...
page = 0
pages_number = 1
while page < pages_number:
page_response = requests.get(url, params={'page': page})
page_response.raise_for_status()
page_payload = page_response.json()
pages_number = page_payload['pages_number']
page += 1
# TODO добавить данные из page_payload в итоговый список
...
Как скачать все страницы. Easy
Названия параметров и формат ответа сервера вымышлены
Нумерация страниц может начинаться с единицы, зависит от API
import requests
from itertools import count
...
for page in count(0):
page_response = requests.get(url, params={'page': page})
page_response.raise_for_status()
page_payload = page_response.json()
if page >= page_payload['pages_number']:
break
# TODO добавить данные из page_payload в итоговый список
...
Как скачать все страницы. Hard
Названия параметров и формат ответа сервера вымышлены
Нумерация страниц может начинаться с единицы, зависит от API
import requests
from itertools import count
...
def fetch_records():
for page in count():
page_response = requests.get(url, params={'page': page})
page_response.raise_for_status()
page_payload = page_response.json()
yield from page_payload['page_records']
if page >= page_payload['pages_number']:
break
Как скачать все страницы. Hard + yield
Названия параметров и формат ответа сервера вымышлены
import requests
def fetch_specific_data():
...
response = requests.get(url, params=params)
# сообщаем внешнему коду о возможной ошибке
response.raise_for_status()
return response.json()['specific_key']
try:
# плохое название, но без конкретики лучше не сделать
some_data = fetch_specific_data()
except requests.exceptions.HTTPError as error:
exit("Can't get data from server:\n{0}".format(error))
Сообщить об ошибке
Если статус ответа будет отличаться от 2xx, то функция выкинет исключение HTTPError. Внешний код узнает о проблеме и корректно завершит работу программы.
Документация
Полная документация библиотеки requests собрана здесь.
Создано для онлайн-курса https://dvmn.org