Введение в работу с библиотекой requests в python

Наш первый запрос

Для начала используем библиотеку Python Requests для чего-то простого: отправим запрос на сайт Scotch.io. Создайте файл script.py и добавьте в него приведенный ниже код.

import requests

res = requests.get('https://scotch.io')

print(res)

Приведенный выше код отправляет запрос GET на Scotch.io. Это тот же тип запроса, который браузер отправляет для просмотра веб-страницы. Отличие заключается в том, что эти запросы не могут передать HTML. Поэтому вместо него приходит необработанный HTML и другая информация из ответа, предоставленного сервером.

В данном случае мы используем функцию .get(). Но библиотека Requests содержит и другие подобные функции: .post() и .put().

Запустите файл script.py.

python script.py

В ответ придет следующее:

Quick Overview of HTTP Requests

HTTP requests are how the web works. Every time you navigate to a web page, your browser makes multiple requests to the web page’s server. The server then responds with all the data necessary to render the page, and your browser then actually renders the page so you can see it.

The generic process is this: a client (like a browser or Python script using Requests) will send some data to a URL, and then the server located at the URL will read the data, decide what to do with it, and return a response to the client. Finally, the client can decide what to do with the data in the response.

Part of the data the client sends in a request is the request method. Some common request methods are GET, POST, and PUT. GET requests are normally for reading data only without making a change to something, while POST and PUT requests generally are for modifying data on the server. So for example, the Stripe API allows you to use POST requests to create a new charge so a user can purchase something from your app.

This article will cover GET requests only because we won’t be modifying any data on a server.

When sending a request from a Python script or inside a web app, you, the developer, gets to decide what gets sent in each request and what to do with the response. So let’s explore that by first sending a request to Scotch.io and then by using a language translation API.

Python requests upload image

In the following example, we are going to upload an image. We create
a web application with Flask.

app.py

#!/usr/bin/env python3

import os
from flask import Flask, request

app = Flask(__name__)

@app.route("/")
def home():
    return 'This is home page'

@app.route("/upload", methods=)
def handleFileUpload():

    msg = 'failed to upload image'

    if 'image' in request.files:

        photo = request.files

        if photo.filename != '':

            photo.save(os.path.join('.', photo.filename))
            msg = 'image uploaded successfully'

    return msg

if __name__ == '__main__':
    app.run()

This is a simple application with two endpoints. The
endpoint checks if there is some image and saves it to the current directory.

upload_file.py

#!/usr/bin/env python3

import requests as req

url = 'http://localhost:5000/upload'

with open('sid.jpg', 'rb') as f:

    files = {'image': f}

    r = req.post(url, files=files)
    print(r.text)

We send the image to the Flask application. The file is specified
in the attribute of the method.

Объект Response

Response — это объект для проверки результатов запроса.

Давайте сделаем тот же запрос, но на этот раз сохраним его в переменную, чтобы мы могли более подробно изучить его атрибуты и поведение:

В этом примере вы захватили значение, возвращаемое значение , которое является экземпляром Response, и сохранили его в переменной response. Название переменной может быть любым.

Код ответа HTTP

Первый кусок данных, который можно получить из ответа — код состояния (он же код ответа HTTP). Код ответа информирует вас о состоянии запроса.

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

Используя вы можете увидеть статус, который вернул вам в ответ сервер:

вернул 200 — это значит, что запрос успешно выполнен и сервер отдал вам запрашиваемые данные.

Иногда эту информацию можно использовать в коде для принятия решений:

Если сервер возвращает 200, то программа выведет , если код ответа 400, то программа выведет .

Requests делает еще один шаг к тому, чтобы сделать это проще. Если вы используете экземпляр Response в условном выражении, то он получит значение , если код ответа между 200 и 400, и False во всех остальных случаях.

Поэтому вы можете сделать проще последний пример, переписав :

Помните, что этот метод не проверяет, что код состояния равен 200.
Причиной этого является то, что ответы с кодом в диапазоне от 200 до 400, такие как и , тоже считаются истинными, так как они дают некоторый обрабатываемый ответ.

Например, статус 204 говорит о том, что запрос был успешным, но в теле ответа нет содержимого.

Поэтому убедитесь, что вы используете этот сокращенный вид записи, только если хотите узнать был ли запрос успешен в целом. А затем обработать код состояния соответствующим образом.

Если вы не хотите проверять код ответа сервера в операторе , то вместо этого вы можете вызвать исключение, если запрос был неудачным. Это можно сделать вызвав :

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

Теперь вы знаете многое о том, что делать с кодом ответа от сервера. Но когда вы делаете GET-запрос, вы редко заботитесь только об ответе сервера — обычно вы хотите увидеть больше.

Далее вы узнаете как просмотреть фактические данные, которые сервер отправил в теле ответа.

Content

Ответ на Get-запрос, в теле сообщения часто содержит некую ценную информацию, известную как «полезная нагрузка» («Payload»). Используя атрибуты и методы Response, вы можете просматривать payload в разных форматах.

Чтобы увидеть содержимое ответа в байтах, используйте :

Пока дает вам доступ к необработанным байтам полезной нагрузки ответа, вы можете захотеть преобразовать их в строку с использованием кодировки символов UTF-8. Response это сделает за вас, когда вы укажите :

Поскольку для декодирования байтов в строки требуется схема кодирования, Requests будет пытаться угадать кодировку на основе заголовков ответа. Вы можете указать кодировку явно, установив перед указанием :

Если вы посмотрите на ответ, то вы увидите, что на самом деле это последовательный JSON контент. Чтобы получить словарь, вы можете взять строку, которую получили из и десериализовать ее с помощью . Однако, более простой способ сделать это — использовать .

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

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

Заголовки

Заголовки ответа могут дать вам полезную информацию, такую как тип ответа и ограничение по времени, в течение которого необходимо кэшировать ответ.
Чтобы посмотреть заголовки, укажите :

возвращает похожий на словарь объект, позволяющий получить доступ к значениям объекта по ключу. Например, чтобы получить тип содержимого ответа, вы можете получить доступ к Content-Type:

Используя ключ или — вы получите одно и то же значение.

Теперь вы узнали основное о Response. Вы увидели его наиболее используемые атрибуты и методы в действии. Давайте сделаем шаг назад и посмотрим как изменяются ответы при настройке Get-запросов.

Коды состояния ответа

Мы можем проверить код состояния ответа:

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

Для удобства также поставляется со встроенным объектом подстановок кодов состояния:

>>> r.status_code == requests.codes.ok
True

Если мы сделали плохой запрос (ошибка клиента или ошибка ответа сервера), то мы можем возбудить исключение с помощью :

>>> bad_r = requests.get('http://httpbin.org/status/404') 
>>> bad_r.status_code 
404
>>> bad_r.raise_for_status() 
Traceback (most recent call last):
  File "requests/models.py", line 832, in raise_for_status
    raise http_error
requests.exceptions.HTTPError: 404 Client Error
Traceback (most recent call last):
  File "requests/models.py", line 832, in raise_for_status
    raise http_error
requests.exceptions.HTTPError: 404 Client Error

Но если status_code для оказался , то когда мы вызываем мы получаем:

>>> r.raise_for_status()
None

Это значит, что все в порядке.

PHP GET request in Symfony

In the following example, we process a GET request in a Symfony application.

$ symfony new symreq
$ cd symreq

A new application is created.

$ composer req annot
$ composer req maker --dev

We install the and components.

$ php bin/console make:controller HomeController

We create a new controller.

src/Controller/HomeController.php

<?php

namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;

class HomeController extends AbstractController
{
    /**
     * @Route("/", name="home", methods={"GET"})
     */
    public function index(Request $request): Response
    {
        $name = $request->query->get('name', 'guest');
        $message = $request->query->get('message', 'hello there');

        $output = "$name says: $message";

        return new Response($output, Response::HTTP_OK,
            ['content-type' => 'text/plain']);
    }
}

Inside the method,
we get the query parameters and create a response.

$name = $request->query->get('name', 'guest');

The GET parameter is retrieved with .
The second parameter of the method is a default value which is used when no
value was retrieved.

$ symfony serve

We start the server.

$ curl 'localhost:8000/?name=Lucia&message=Cau'
Lucia says: Cau

We generate a GET request with curl.

Python requests post value

The method dispatches a POST request on the given
URL, providing the key/value pairs for the fill-in form content.

post_value.py

#!/usr/bin/env python3

import requests as req

data = {'name': 'Peter'}

resp = req.post("https://httpbin.org/post", data)
print(resp.text)

The script sends a request with a key having value.
The POST request is issued with the method.

$ ./post_value.py
{
  "args": {},
  "data": "",
  "files": {},
  "form": {
    "name": "Peter"
  },
  "headers": {
    "Accept": "*/*",
    "Accept-Encoding": "gzip, deflate",
    "Content-Length": "10",
    "Content-Type": "application/x-www-form-urlencoded",
    "Host": "httpbin.org",
    "User-Agent": "python-requests/2.21.0"
  },
  "json": null,
  ...
}

This is the output of the script.

Заголовки

Также в ответе вы можете получить заголовки. Вы можете посмотреть их, используя словарь headers для объекта response.

script.py

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

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

Обычно требуется заголовок content type, поскольку он показывает формат данных, например HTML, JSON, PDF, обычный текст и т. д. Однако заголовок content type обрабатывается библиотекой Requests, и вы имеете доступ ко всем возвращаемым данным.

Retrieving definitions from a dictionary

In the following example, we find definitions of a term
on the www.dictionary.com.
To parse HTML, we use the module.

$ pip install lxml

We install the module with
the tool.

get_term.py

#!/usr/bin/env python3

import requests as req
from lxml import html
import textwrap

term = "dog"

resp = req.get("http://www.dictionary.com/browse/" + term)
root = html.fromstring(resp.content)

for sel in root.xpath("//span"):

    if sel.text:

        s = sel.text.strip()

        if (len(s) > 3):

            print(textwrap.fill(s, width=50))

In this script, we find the definitions of the term dog on .
The module is used to parse the HTML code.

Note: The tags that contain the definitions may change overnight.
In such case we would need to adapt the script.

from lxml import html

The module can be used to parse HTML.

import textwrap

The module is used to wrap text to a certain width.

resp = req.get("http://www.dictionary.com/browse/" + term)

To perform a search, we append the term at the end of the URL.

root = html.fromstring(resp.content)

We need to use rather than
because implicitly expects bytes as input.
(The returns content in bytes whereas
as Unicode text.

for sel in root.xpath("//span"):

    if sel.text:

        s = sel.text.strip()

        if (len(s) > 3):

            print(textwrap.fill(s, width=50))

We parse the content. The main definitions are located inside the tag, which
has the attribute.
We improve the formatting by removing excessive white space and stray
characters. The text width has maximum of 50 characters. Note that such parsing
is subject to change.

$ ./get_term.py
a domesticated canid,
any carnivore of the dog family Canidae, having
prominent canine teeth and, in the wild state, a
long and slender muzzle, a deep-chested muscular
body, a bushy tail, and large, erect ears.
...

This is a partial list of the definitions.

Наш первый запрос

Для начала мы используем библиотеку Requests для отправки запроса на сайт Scotch.io. Создайте файл с именем и добавьте в него следующий код. В этой статье мы рассматриваем небольшое количество кода, поэтому если что-то изменится, вы можете просто обновить существующий код вместо добавления новых строк.

script.py

Этот код просто отправляет запрос GET на сайт Scotch.io. Это такой же тип запроса, какой используется вашим браузером для просмотра этой страницы, и единственное отличие заключается в том, что библиотека Requests не может выполнить рендеринг кода HTML, и поэтому вы получите просто код HTML и другую информацию, содержащуюся в ответе.

Здесь мы используем функцию , однако Requests также позволяет использовать при отправке запросов и другие функции, в том числе и .

Для отправки запроса нужно запустить файл script.py.

Вот что вы получите в результате: запуск .

User agent

In this section, we specify the name of the user agent. We create our
own Python HTTP server.

http_server.py

#!/usr/bin/env python3

from http.server import BaseHTTPRequestHandler, HTTPServer

class MyHandler(BaseHTTPRequestHandler):

    def do_GET(self):

        message = "Hello there"

        self.send_response(200)

        if self.path == '/agent':

            message = self.headers

        self.send_header('Content-type', 'text/html')
        self.end_headers()

        self.wfile.write(bytes(message, "utf8"))

        return


def main():

    print('starting server on port 8081...')

    server_address = ('127.0.0.1', 8081)
    httpd = HTTPServer(server_address, MyHandler)
    httpd.serve_forever()

main()

We have a simple Python HTTP server.

if self.path == '/agent':

    message = self.headers

If the path contains , we return
the specified user agent.

user_agent.py

#!/usr/bin/env python3

import requests as req

headers = {'user-agent': 'Python script'}

resp = req.get("http://localhost:8081/agent", headers=headers)
print(resp.text)

This script creates a simple GET request to our Python HTTP server.
To add HTTP headers to a request, we pass in a dictionary to the
parameter.

headers = {'user-agent': 'Python script'}

The header values are placed in a Python dictionary.

resp = req.get("http://localhost:8081/agent", headers=headers)

The values are passed to the parameter.

$ simple_server.py
starting server on port 8081...

First, we start the server.

$ ./user_agent.py
Python script

Then we run the script. The server responded with the name of the agent that we
have sent with the request.

Examples¶

Here is an example session that uses the method:

>>> import http.client
>>> conn = http.client.HTTPSConnection("www.python.org")
>>> conn.request("GET", "/")
>>> r1 = conn.getresponse()
>>> print(r1.status, r1.reason)
200 OK
>>> data1 = r1.read()  # This will return entire content.
>>> # The following example demonstrates reading data in chunks.
>>> conn.request("GET", "/")
>>> r1 = conn.getresponse()
>>> while chunk := r1.read(200):
...     print(repr(chunk))
b'<!doctype html>\n<!--[if"...
...
>>> # Example of an invalid request
>>> conn = http.client.HTTPSConnection("docs.python.org")
>>> conn.request("GET", "/parrot.spam")
>>> r2 = conn.getresponse()
>>> print(r2.status, r2.reason)
404 Not Found
>>> data2 = r2.read()
>>> conn.close()

Here is an example session that uses the method. Note that the
method never returns any data.

>>> import http.client
>>> conn = http.client.HTTPSConnection("www.python.org")
>>> conn.request("HEAD", "/")
>>> res = conn.getresponse()
>>> print(res.status, res.reason)
200 OK
>>> data = res.read()
>>> print(len(data))

>>> data == b''
True

Here is an example session that shows how to requests:

>>> import http.client, urllib.parse
>>> params = urllib.parse.urlencode({'@number' 12524, '@type' 'issue', '@action' 'show'})
>>> headers = {"Content-type" "application/x-www-form-urlencoded",
...            "Accept" "text/plain"}
>>> conn = http.client.HTTPConnection("bugs.python.org")
>>> conn.request("POST", "", params, headers)
>>> response = conn.getresponse()
>>> print(response.status, response.reason)
302 Found
>>> data = response.read()
>>> data
b'Redirecting to <a href="http://bugs.python.org/issue12524">http://bugs.python.org/issue12524</a>'
>>> conn.close()

Client side requests are very similar to requests. The
difference lies only the server side where HTTP server will allow resources to
be created via request. It should be noted that custom HTTP methods
are also handled in by setting the appropriate
method attribute. Here is an example session that shows how to send a
request using http.client:

Python Tutorial

Python HOMEPython IntroPython Get StartedPython SyntaxPython CommentsPython Variables
Python Variables
Variable Names
Assign Multiple Values
Output Variables
Global Variables
Variable Exercises

Python Data TypesPython NumbersPython CastingPython Strings
Python Strings
Slicing Strings
Modify Strings
Concatenate Strings
Format Strings
Escape Characters
String Methods
String Exercises

Python BooleansPython OperatorsPython Lists
Python Lists
Access List Items
Change List Items
Add List Items
Remove List Items
Loop Lists
List Comprehension
Sort Lists
Copy Lists
Join Lists
List Methods
List Exercises

Python Tuples
Python Tuples
Access Tuples
Update Tuples
Unpack Tuples
Loop Tuples
Join Tuples
Tuple Methods
Tuple Exercises

Python Sets
Python Sets
Access Set Items
Add Set Items
Remove Set Items
Loop Sets
Join Sets
Set Methods
Set Exercises

Python Dictionaries
Python Dictionaries
Access Items
Change Items
Add Items
Remove Items
Loop Dictionaries
Copy Dictionaries
Nested Dictionaries
Dictionary Methods
Dictionary Exercise

Python If…ElsePython While LoopsPython For LoopsPython FunctionsPython LambdaPython ArraysPython Classes/ObjectsPython InheritancePython IteratorsPython ScopePython ModulesPython DatesPython MathPython JSONPython RegExPython PIPPython Try…ExceptPython User InputPython String Formatting

urllib.request Restrictions¶

  • Currently, only the following protocols are supported: HTTP (versions 0.9 and
    1.0), FTP, local files, and data URLs.

    Changed in version 3.4: Added support for data URLs.

  • The caching feature of has been disabled until someone
    finds the time to hack proper processing of Expiration time headers.

  • There should be a function to query whether a particular URL is in the cache.

  • For backward compatibility, if a URL appears to point to a local file but the
    file can’t be opened, the URL is re-interpreted using the FTP protocol. This
    can sometimes cause confusing error messages.

  • The and functions can cause arbitrarily
    long delays while waiting for a network connection to be set up. This means
    that it is difficult to build an interactive Web client using these functions
    without using threads.

  • The data returned by or is the raw data
    returned by the server. This may be binary data (such as an image), plain text
    or (for example) HTML. The HTTP protocol provides type information in the reply
    header, which can be inspected by looking at the Content-Type
    header. If the returned data is HTML, you can use the module
    to parse it.

  • The code handling the FTP protocol cannot differentiate between a file and a
    directory. This can lead to unexpected behavior when attempting to read a URL
    that points to a file that is not accessible. If the URL ends in a , it is
    assumed to refer to a directory and will be handled accordingly. But if an
    attempt to read a file leads to a 550 error (meaning the URL cannot be found or
    is not accessible, often for permission reasons), then the path is treated as a
    directory in order to handle the case when a directory is specified by a URL but
    the trailing has been left off. This can cause misleading results when
    you try to fetch a file whose read permissions make it inaccessible; the FTP
    code will try to read it, fail with a 550 error, and then perform a directory
    listing for the unreadable file. If fine-grained control is needed, consider
    using the module, subclassing , or changing
    _urlopener to meet your needs.

HTTP-коды состояний

Первые данные, которые мы получим посредством Response, будут коды состояния. Они сообщают о статусе нашего запроса.

К примеру, статус 200 OK означает, что запрос был успешно выполнен. А известная всем ошибка 404 NOT FOUND скажет нам, что запрашиваемый ресурс найден не был. Таких статусных информационных кодов существует довольно много.

Давайте с помощью .status_code, увидим код состояния, возвращаемый с сервера.

    >>> response.status_code
200

В нашем случае .status_code вернул 200, что означает успешно выполненный запрос.
Кстати, иногда полученная информация используется при написании кода:

    if response.status_code == 200
    print('Success!')
elif response.status_code == 404
    print('Not Found.')

HTTP status codes¶

Supported,
IANA-registered
status codes available in are:

Code

Enum Name

Details

HTTP/1.1 RFC 7231, Section 6.2.1

HTTP/1.1 RFC 7231, Section 6.2.2

WebDAV RFC 2518, Section 10.1

An HTTP Status Code for Indicating Hints RFC 8297

HTTP/1.1 RFC 7231, Section 6.3.1

HTTP/1.1 RFC 7231, Section 6.3.2

HTTP/1.1 RFC 7231, Section 6.3.3

HTTP/1.1 RFC 7231, Section 6.3.4

HTTP/1.1 RFC 7231, Section 6.3.5

HTTP/1.1 RFC 7231, Section 6.3.6

HTTP/1.1 RFC 7233, Section 4.1

WebDAV RFC 4918, Section 11.1

WebDAV Binding Extensions RFC 5842, Section 7.1 (Experimental)

Delta Encoding in HTTP RFC 3229, Section 10.4.1

HTTP/1.1 RFC 7231, Section 6.4.1

HTTP/1.1 RFC 7231, Section 6.4.2

HTTP/1.1 RFC 7231, Section 6.4.3

HTTP/1.1 RFC 7231, Section 6.4.4

HTTP/1.1 RFC 7232, Section 4.1

HTTP/1.1 RFC 7231, Section 6.4.5

HTTP/1.1 RFC 7231, Section 6.4.7

Permanent Redirect RFC 7238, Section 3 (Experimental)

HTTP/1.1 RFC 7231, Section 6.5.1

HTTP/1.1 Authentication RFC 7235, Section 3.1

HTTP/1.1 RFC 7231, Section 6.5.2

HTTP/1.1 RFC 7231, Section 6.5.3

HTTP/1.1 RFC 7231, Section 6.5.4

HTTP/1.1 RFC 7231, Section 6.5.5

HTTP/1.1 RFC 7231, Section 6.5.6

HTTP/1.1 Authentication RFC 7235, Section 3.2

HTTP/1.1 RFC 7231, Section 6.5.7

HTTP/1.1 RFC 7231, Section 6.5.8

HTTP/1.1 RFC 7231, Section 6.5.9

HTTP/1.1 RFC 7231, Section 6.5.10

HTTP/1.1 RFC 7232, Section 4.2

HTTP/1.1 RFC 7231, Section 6.5.11

HTTP/1.1 RFC 7231, Section 6.5.12

HTTP/1.1 RFC 7231, Section 6.5.13

HTTP/1.1 Range Requests RFC 7233, Section 4.4

HTTP/1.1 RFC 7231, Section 6.5.14

HTCPCP/1.0 RFC 2324, Section 2.3.2

HTTP/2 RFC 7540, Section 9.1.2

WebDAV RFC 4918, Section 11.2

WebDAV RFC 4918, Section 11.3

WebDAV RFC 4918, Section 11.4

Using Early Data in HTTP RFC 8470

HTTP/1.1 RFC 7231, Section 6.5.15

Additional HTTP Status Codes RFC 6585

Additional HTTP Status Codes RFC 6585

Additional HTTP Status Codes RFC 6585

An HTTP Status Code to Report Legal Obstacles RFC 7725

HTTP/1.1 RFC 7231, Section 6.6.1

HTTP/1.1 RFC 7231, Section 6.6.2

HTTP/1.1 RFC 7231, Section 6.6.3

HTTP/1.1 RFC 7231, Section 6.6.4

HTTP/1.1 RFC 7231, Section 6.6.5

HTTP/1.1 RFC 7231, Section 6.6.6

Transparent Content Negotiation in HTTP RFC 2295, Section 8.1 (Experimental)

WebDAV RFC 4918, Section 11.5

WebDAV Binding Extensions RFC 5842, Section 7.2 (Experimental)

An HTTP Extension Framework RFC 2774, Section 7 (Experimental)

Additional HTTP Status Codes RFC 6585, Section 6

In order to preserve backwards compatibility, enum values are also present
in the module in the form of constants. The enum name is
equal to the constant name (i.e. is also available as
).

Changed in version 3.7: Added status code.

New in version 3.8: Added status code.

New in version 3.9: Added , and status codes.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector