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

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

Вступление

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

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

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

Установить этот пакет, как и большинство других пакетов Python, довольно просто. Вы можете либо загрузить исходный код запросов с 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) 

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

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

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

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

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

Инструменты разработчика Chrome сhttpbin{.ezlazyload .img-responsive}

Содержание «Заголовков ответа» является нашим обязательным элементом. Вы можете увидеть пары ключ-значение, содержащие различную информацию о ресурсе и запросе. Попробуем разобрать эти значения с помощью библиотеки 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"} 

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

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

Выполнение запросов POST

Запросы 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/ 
 [<Response [301]>, <Response [301]>] 
 200 

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

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

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

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

 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"} 

Путь httpbin / cookies / set / {имя} / {значение} установит файл 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" добавляется к 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 имеет значение True , requests будут передавать контент в потоковом режиме. Если stream имеет значение 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 

Для загрузки или потоковой передачи контента iter_content() .

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

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

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

  • ConnectionError выдается в случае DNS failure , refused connection или любых других проблем, связанных с подключением.
  • Timeout увеличивается, если время ожидания запроса истекло.
  • TooManyRedirects возникает, если запрос превышает максимальное количество предопределенных перенаправлений.
  • HTTPError возникает для недопустимых ответов HTTP.

Более полный список и описание исключений, с которыми вы можете столкнуться, можно найти в документации .

Заключение

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

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

Licensed under CC BY-NC-SA 4.0
comments powered by Disqus