Рубрики
Без рубрики

Модуль Запросов Python

Автор оригинала: N Kaushik.

Вступление

Работа с HTTP-запросами-непростая задача на любом языке программирования. Если говорить о Python, то он поставляется с двумя встроенными модулями, urllib и urllib2 , для обработки операций, связанных с HTTP. Оба модуля имеют разный набор функций, и много раз их нужно использовать вместе. Основной недостаток использования urllib заключается в том, что он сбивает с толку (несколько методов доступны как в urllib , так и в urllib2 ), документация не ясна, и нам нужно написать много кода, чтобы сделать даже простой HTTP-запрос.

Чтобы сделать эти вещи проще, доступна одна простая в использовании сторонняя библиотека, известная как Requests , и большинство разработчиков предпочитают использовать ее вместо urllib /| urllib2 . Это лицензированная HTTP-библиотека Apache2, работающая на urllib3 и httplib .

Установка модуля Запросов

Установка этого пакета, как и большинства других пакетов Python, довольно проста. Вы можете либо скачать исходный код Requests с Github и установить его, либо использовать pip:

$ pip install requests

Для получения дополнительной информации о процессе установки обратитесь к официальной документации .

Чтобы проверить установку, вы можете попробовать импортировать ее, как показано ниже:

import requests

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

Создание запроса GET

GET на сегодняшний день является наиболее часто используемым методом HTTP. Мы можем использовать GET-запрос для получения данных из любого места назначения. Позвольте мне начать с простого примера. Предположим, мы хотим получить содержимое домашней страницы нашего веб-сайта и распечатать полученные HTML-данные. Используя модуль запросов, мы можем сделать это, как показано ниже:

import requests

r = requests.get('https://api.github.com/events')
print(r.content)

Он напечатает ответ в закодированном виде. Если вы хотите увидеть фактический текстовый результат HTML-страницы, вы можете прочитать свойство .text этого объекта. Аналогично, свойство status_code выводит текущий код состояния URL-адреса:

import requests

r = requests.get('https://api.github.com/events')
print(r.text)
print(r.status_code)

запросы расшифруют необработанный контент и покажут вам результат. Если вы хотите проверить , какой тип encoding используется requests , вы можете распечатать это значение, вызвав .encoding . Даже тип кодировки можно изменить, изменив ее значение. Ну разве это не просто?

Чтение ответа

Ответ HTTP-запроса может содержать множество заголовков, содержащих различную информацию.

http bin – это популярный веб-сайт для тестирования различных операций HTTP. В этой статье мы будем использовать httpbin/get для анализа ответа на запрос GET. Прежде всего, нам нужно выяснить заголовок ответа и как он выглядит. Вы можете использовать любой современный веб-браузер, чтобы найти его, но для этого примера мы будем использовать браузер Google Chrome.

  • В Chrome откройте URL-адрес http://httpbin.org/get , щелкните правой кнопкой мыши в любом месте страницы и выберите опцию “Проверить”.
  • Это откроет новое окно в вашем браузере. Обновите страницу и перейдите на вкладку “Сеть”.
  • Эта вкладка “Сеть” покажет вам все различные типы сетевых запросов, выполняемых браузером. Нажмите на запрос “get” в столбце “Name” и выберите вкладку “Headers” справа.
Инструменты разработчика Chrome с httpbin

Содержание “Заголовков ответов” является нашим обязательным элементом. Вы можете увидеть пары ключ-значение, содержащие различную информацию о ресурсе и запросе. Давайте попробуем разобрать эти значения с помощью библиотеки requests :

import requests

r = requests.get('http://httpbin.org/get')
print(r.headers['Access-Control-Allow-Credentials'])
print(r.headers['Access-Control-Allow-Origin'])
print(r.headers['CONNECTION'])
print(r.headers['content-length'])
print(r.headers['Content-Type'])
print(r.headers['Date'])
print(r.headers['server'])
print(r.headers['via'])

Мы извлекли информацию о заголовке с помощью r.headers и можем получить доступ к каждому значению заголовка с помощью определенных ключей. Обратите внимание, что ключ не чувствителен к регистру .

Аналогично, давайте попробуем получить доступ к значению ответа. Приведенный выше заголовок показывает, что ответ находится в формате JSON: (Content-type: application/json) . Библиотека запросов поставляется с одним встроенным парсером JSON, и мы можем использовать requests.get('url').json() для анализа его как объекта JSON. Затем значение для каждого ключа результатов ответа может быть легко проанализировано, как показано ниже:

import requests

r = requests.get('http://httpbin.org/get')

response = r.json()
print(r.json())
print(response['args'])
print(response['headers'])
print(response['headers']['Accept'])
print(response['headers']['Accept-Encoding'])
print(response['headers']['Connection'])
print(response['headers']['Host'])
print(response['headers']['User-Agent'])
print(response['origin'])
print(response['url'])

Приведенный выше код выведет нижеприведенный вывод:

{'headers': {'Host': 'httpbin.org', 'Accept-Encoding': 'gzip, deflate', 'Connection': 'close', 'Accept': '*/*', 'User-Agent': 'python-requests/2.9.1'}, 'url': 'http://httpbin.org/get', 'args': {}, 'origin': '103.9.74.222'}
{}
{'Host': 'httpbin.org', 'Accept-Encoding': 'gzip, deflate', 'Connection': 'close', 'Accept': '*/*', 'User-Agent': 'python-requests/2.9.1'}
*/*
gzip, deflate
close
httpbin.org
python-requests/2.9.1
103.9.74.222
http://httpbin.org/get

Третья строка, т. е. r.json() , выводит значение JSON ответа. Мы сохранили значение JSON в переменной response , а затем распечатали значение для каждого ключа. Обратите внимание, что в отличие от предыдущего примера, ключ-значение чувствительно к регистру.

Подобно JSON и текстовому контенту, мы можем использовать requests для чтения содержимого ответа в байтах для нетекстовых запросов с помощью свойства .content . Это автоматически декодирует gzip и deflate закодированные файлы.

Передача параметров в GET

В некоторых случаях вам нужно будет передать параметры вместе с вашими запросами GET, которые принимают форму строк запроса. Для этого нам нужно передать эти значения в параметр params , как показано ниже:

import requests

payload = {'user_name': 'admin', 'password': 'password'}
r = requests.get('http://httpbin.org/get', params=payload)

print(r.url)
print(r.text)

Здесь мы присваиваем значения наших параметров переменной payload , а затем запросу GET через params . Приведенный выше код вернет следующий вывод:

http://httpbin.org/get?password=password&user_name=admin
{"args":{"password":"password","user_name":"admin"},"headers":{"Accept":"*/*","Accept-Encoding":"gzip, deflate","Connection":"close","Host":"httpbin.org","User-Agent":"python-requests/2.9.1"},"origin":"103.9.74.222","url":"http://httpbin.org/get?password=password&user_name=admin"}

Как вы можете видеть, библиотека запросов автоматически превратила наш словарь параметров в строку запроса и прикрепила его к URL-адресу.

Обратите внимание, что вы должны быть осторожны с тем, какие данные вы передаете через GET-запросы, так как полезная нагрузка видна в URL-адресе, как вы можете видеть в выходных данных выше.

Создание ПОЧТОВЫХ запросов

HTTP POST – запросы противоположны GET-запросам, поскольку они предназначены для отправки данных на сервер, а не для их извлечения. Хотя запросы POST также могут получать данные в ответе, как и запросы GET.

Вместо использования метода get() нам нужно использовать метод post () . Для передачи аргумента мы можем передать его внутри параметра data :

import requests

payload = {'user_name': 'admin', 'password': 'password'}
r = requests.post("http://httpbin.org/post", data=payload)
print(r.url)
print(r.text)

Выход:

http://httpbin.org/post
{"args":{},"data":"","files":{},"form":{"password":"password","user_name":"admin"},"headers":{"Accept":"*/*","Accept-Encoding":"gzip, deflate","Connection":"close","Content-Length":"33","Content-Type":"application/x-www-form-urlencoded","Host":"httpbin.org","User-Agent":"python-requests/2.9.1"},"json":null,"origin":"103.9.74.222","url":"http://httpbin.org/post"}

По умолчанию данные будут “закодированы в форме”. Вы также можете передавать более сложные запросы заголовка, такие как кортеж, если несколько значений имеют один и тот же ключ, строку вместо словаря или составной кодированный файл.

Отправка файлов с помощью POST

Иногда нам нужно отправить один или несколько файлов одновременно на сервер. Например, если пользователь отправляет форму и форма включает в себя различные поля формы для загрузки файлов, таких как изображение профиля пользователя, резюме пользователя и т. Д. Запросы могут обрабатывать несколько файлов по одному запросу. Это можно сделать, поместив файлы в список кортежей, как показано ниже:

import requests

url = 'http://httpbin.org/post'
file_list = [
    ('image', ('image1.jpg', open('image1.jpg', 'rb'), 'image/png')),
    ('image', ('image2.jpg', open('image2.jpg', 'rb'), 'image/png'))
]

r = requests.post(url, files=file_list)
print(r.text)

Кортежи, содержащие информацию о файлах, имеют вид (field_name, file_info) .

Другие Типы HTTP-запросов

Подобно GET и POST, мы можем выполнять другие HTTP-запросы, такие как PUT, DELETE, HEAD и OPTIONS, используя библиотеку requests , как показано ниже:

import requests

requests.put('url', data={'key': 'value'})
requests.delete('url')
requests.head('url')
requests.options('url')

Обработка Перенаправлений

Перенаправление в HTTP означает перенаправление сетевого запроса на другой URL-адрес. Например, если мы сделаем запрос на ” http://www.github.com “, он перенаправит на ” https://github.com ” использование 301 редиректа .

import requests

r = requests.post("http://www.github.com")
print(r.url)
print(r.history)
print(r.status_code)

Выход:

https://github.com/
[, ]
200

Как вы можете видеть , процесс перенаправления автоматически обрабатывается requests , поэтому вам не нужно заниматься им самостоятельно. Свойство history содержит список всех объектов ответа, созданных для завершения перенаправления. В нашем примере два объекта Response были созданы с кодом ответа 301. Ответы HTTP 301 и 302 используются для постоянного и временного перенаправления соответственно.

Если вы не хотите, чтобы библиотека запросов автоматически следовала за перенаправлениями, то вы можете отключить ее, передав вместе с запросом параметр allow_redirects=False .

Обработка таймаутов

Еще одна важная конфигурация-это указание нашей библиотеке, как обрабатывать тайм-ауты или запросы, которые слишком долго возвращаются. Мы можем настроить requests так, чтобы прекратить ожидание сетевых запросов с помощью параметра timeout . По умолчанию запросы не будут тайм-аута. Таким образом, если мы не настроим это свойство, наша программа может зависнуть на неопределенный срок, что не является той функциональностью, которая вам нужна в процессе, заставляющем пользователя ждать.

import requests

requests.get('http://www.google.com', timeout=1)

Здесь исключение будет выдано, если сервер не ответит в течение 1 секунды (что по-прежнему агрессивно для реального приложения). Чтобы это происходило чаще (для примера), вам нужно установить ограничение тайм-аута на гораздо меньшее значение, например 0,001.

Тайм – аут может быть настроен как для операций “подключение”, так и для операций “чтение” запроса с помощью кортежа, что позволяет указать оба значения отдельно:

import requests

requests.get('http://www.google.com', timeout=(5, 14))

Здесь тайм-аут “подключения” составляет 5 секунд, а тайм-аут “чтения” – 14 секунд. Это позволит вашему запросу потерпеть неудачу гораздо быстрее, если он не сможет подключиться к ресурсу, а если он подключится, то это даст ему больше времени для загрузки данных.

Файлы cookie и пользовательские заголовки

Ранее мы уже видели, как получить доступ к заголовкам с помощью свойства headers . Точно так же мы можем получить доступ к файлам cookie из ответа, используя свойство cookies .

Например, в приведенном ниже примере показано, как получить доступ к файлу cookie с именем cookie_name :

import requests

r = requests.get('http://www.examplesite.com')
r.cookies['cookie_name']

Мы также можем отправлять пользовательские файлы cookie на сервер, предоставляя словарь параметру cookies в нашем запросе GET.

import requests

custom_cookie = {'cookie_name': 'cookie_value'}
r = requests.get('http://www.examplesite.com/cookies', cookies=custom_cookie)

Файлы cookie также могут быть переданы в объект Cookie Jar . Это позволяет вам предоставлять файлы cookie для другого пути.

import requests

jar = requests.cookies.RequestsCookieJar()
jar.set('cookie_one', 'one', domain='httpbin.org', path='/cookies')
jar.set('cookie_two', 'two', domain='httpbin.org', path='/other')

r = requests.get('https://httpbin.org/cookies', cookies=jar)
print(r.text)

Выход:

{"cookies":{"cookie_one":"one"}}

Аналогично, мы можем создавать пользовательские заголовки, назначая словарь заголовку запроса с помощью параметра headers .

import requests

custom_header = {'user-agent': 'customUserAgent'}

r = requests.get('https://samplesite.org', headers=custom_header)

Объект Сеанса

Объект сеанса в основном используется для сохранения определенных параметров, таких как файлы cookie, в различных HTTP-запросах. Объект сеанса может использовать одно TCP-соединение для обработки нескольких сетевых запросов и ответов, что приводит к повышению производительности.

import requests

first_session = requests.Session()
second_session = requests.Session()

first_session.get('http://httpbin.org/cookies/set/cookieone/111')
r = first_session.get('http://httpbin.org/cookies')
print(r.text)

second_session.get('http://httpbin.org/cookies/set/cookietwo/222')
r = second_session.get('http://httpbin.org/cookies')
print(r.text)

r = first_session.get('http://httpbin.org/anything')
print(r.text)

Выход:

{"cookies":{"cookieone":"111"}}

{"cookies":{"cookietwo":"222"}}

{"args":{},"data":"","files":{},"form":{},"headers":{"Accept":"*/*","Accept-Encoding":"gzip, deflate","Connection":"close","Cookie":"cookieone=111","Host":"httpbin.org","User-Agent":"python-requests/2.9.1"},"json":null,"method":"GET","origin":"103.9.74.222","url":"http://httpbin.org/anything"}

Http binpath /cookies/set/{name}/{value} установит файл cookie с name и value . Здесь мы устанавливаем разные значения файлов cookie как для объектов first_session , так и для объектов second_session . Вы можете видеть, что один и тот же файл cookie возвращается во всех будущих сетевых запросах для определенного сеанса.

Аналогично, мы можем использовать объект сеанса для сохранения определенных параметров для всех запросов.

import requests

first_session = requests.Session()

first_session.cookies.update({'default_cookie': 'default'})

r = first_session.get('http://httpbin.org/cookies', cookies={'first-cookie': '111'})
print(r.text)

r = first_session.get('http://httpbin.org/cookies')
print(r.text)

Выход:

{"cookies":{"default_cookie":"default","first-cookie":"111"}}

{"cookies":{"default_cookie":"default"}}

Как вы можете видеть, default_cookie отправляется с каждым запросом сеанса. Если мы добавим какой-либо дополнительный параметр к объекту cookie , он добавится к default_cookie . "first-cookie": "111" is append to the default cookie "default_cookie": "default"

Использование Прокси-серверов

Аргумент proxies используется для настройки прокси-сервера для использования в ваших запросах.

http = "http://10.10.1.10:1080"
https = "https://10.10.1.11:3128"
ftp = "ftp://10.10.1.10:8080"

proxy_dict = {
  "http": http,
  "https": https,
  "ftp": ftp
}

r = requests.get('http://sampleurl.com', proxies=proxy_dict)

Библиотека requests также поддерживает SOCKS прокси. Это необязательная функция, и она требует установки зависимости requests[socks] перед использованием. Как и раньше, вы можете установить его с помощью pip:

$ pip install requests[socks]

После установки вы можете использовать его, как показано здесь:

proxies = {
  'http': 'socks5:user:[email protected]:port'
  'https': 'socks5:user:[email protected]:port'
}

Обработка SSL

Мы также можем использовать библиотеку запросов для проверки HTTPS-сертификата веб-сайта в обход verify=true с помощью запроса.

import requests

r = requests.get('https://www.github.com', verify=True)

Это вызовет ошибку, если возникнут какие-либо проблемы с SSL сайта. Если вы не хотите верить, просто передайте False вместо True . Этот параметр имеет значение True по умолчанию.

Загрузка файла

Для загрузки файла с помощью requests мы можем либо загрузить его путем потоковой передачи содержимого , либо напрямую загрузить все целиком. Флаг stream используется для обозначения обоих вариантов поведения.

Как вы, наверное, догадались , если stream is True , то requests будет транслировать контент. Если stream is False , то все содержимое будет загружено в память перед тем, как вернуть его вам.

Для потоковой передачи контента мы можем итерировать контент кусок за куском с помощью метода iter_content или итерировать строку за строкой с помощью iter_line . В любом случае, он будет загружать файл по частям.

Например:

import requests

r = requests.get('https://cdn.pixabay.com/photo/2018/07/05/02/50/sun-hat-3517443_1280.jpg', stream=True)
downloaded_file = open("sun-hat.jpg", "wb")
for chunk in r.iter_content(chunk_size=256):
    if chunk:
        downloaded_file.write(chunk)

Приведенный выше код загрузит изображение из Pixabay сервер и сохранить его в локальном файле, sun-hat.jpg .

Мы также можем считывать необработанные данные, используя свойство raw и stream=True в запросе.

import requests

r = requests.get("http://exampleurl.com", stream=True)
r.raw

Для загрузки или потоковой передачи контента предпочтительным способом является other_content () .

Ошибки и исключения

запросы выбрасывают различные типы исключений и ошибок, если когда-либо возникает сетевая проблема. Все исключения наследуются от requests.exceptions.RequestException класс.

Вот краткое описание распространенных ошибок, с которыми вы можете столкнуться:

  • ConnectionError исключение создается в случае сбоя DNS , отказа в соединении или любых других проблем, связанных с соединением.
  • Timeout вызывается, если время ожидания запроса истекло.
  • Слишком много перенаправлений возникает, если запрос превышает максимальное количество предопределенных перенаправлений.
  • HTTP Error exception вызывается для недопустимых HTTP-ответов.

Для получения более полного списка и описания исключений, с которыми вы можете столкнуться, ознакомьтесь с documentation .

Вывод

В этом уроке я объяснил вам многие особенности библиотеки requests и различные способы ее использования. Вы можете использовать библиотеку requests не только для взаимодействия с REST API, но и для очистки данных с веб-сайта или загрузки файлов из Интернета.

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