Python’s requests library (guide)

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

Часто вы хотите послать какие-то данные в строке запроса URL. Если вы строите URL вручную, то эти данные будут представлены в нем в виде пар ключ-значение после знака вопроса. Например, . Requests позволяет передать эти аргументы в качестве словаря, используя аргумент . В качестве примера, если вы хотите передать и ресурсу , вы должны использовать следующий код:

>>> payload = {'key1': 'value1', 'key2': 'value2'}
>>> r = requests.get("http://httpbin.org/get", params=payload)

Вы можете видеть, что URL был закодирован правильно:

>>> print(r.url)
http://httpbin.org/get?key2=value2&key1=value1

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

Properties and Methods

Property/Method Description
apparent_encoding Try it Returns the apparent encoding
close() Try it Closes the connection to the server
content Try it Returns the content of the response, in bytes
cookies Try it Returns a CookieJar object with the cookies sent back from the server
elapsed Try it Returns a timedelta object with the time elapsed from sending the request to the arrival of the response
encoding Try it Returns the encoding used to decode r.text
headers Try it Returns a dictionary of response headers
history Try it Returns a list of response objects holding the history of request (url)
is_permanent_redirect Try it Returns True if the response is the permanent redirected url, otherwise False
is_redirect Try it Returns True if the response was redirected, otherwise False
iter_content() Try it Iterates over the response
iter_lines() Try it Iterates over the lines of the response
json() Try it Returns a JSON object of the result (if the result was written in JSON format, if not it raises an error)
links Try it Returns the header links
next Try it Returns a PreparedRequest object for the next request in a redirection
ok Try it Returns True if status_code is less than 400, otherwise False
raise_for_status() Try it If an error occur, this method returns a HTTPError object
reason Try it Returns a text corresponding to the status code
request Try it Returns the request object that requested this response
status_code Try it Returns a number that indicates the status (200 is OK, 404 is Not Found)
text Try it Returns the content of the response, in unicode
url Try it Returns the URL of the response

Обработка ошибок

Всегда хорошо реализовать обработку ошибок. Это не только поможет избежать неожиданного выхода скрипта, но также помоет вести журнал ошибок и уведомлений. Используя запросы Python, я предпочитаю ловить ошибки следующим образом:

Попробуйте:

Python

try:
# Логика нашего парсера.
r = requests.get(‘https://python-scripts.com’)

except requests.ConnectionError as e:
print(«OOPS!! Connection Error. Make sure you are connected to Internet. Technical Details given below.\n»)
print(str(e))
except requests.Timeout as e:
print(«OOPS!! Timeout Error»)
print(str(e))
except requests.RequestException as e:
print(«OOPS!! General Error»)
print(str(e))
except KeyboardInterrupt:
print(«Someone closed the program»)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

try

# Логика нашего парсера.

r=requests.get(‘https://python-scripts.com’)

exceptrequests.ConnectionError ase

print(«OOPS!! Connection Error. Make sure you are connected to Internet. Technical Details given below.\n»)

print(str(e))

exceptrequests.Timeout ase

print(«OOPS!! Timeout Error»)

print(str(e))

exceptrequests.RequestException ase

print(«OOPS!! General Error»)

print(str(e))

exceptKeyboardInterrupt

print(«Someone closed the program»)

Проверьте последнюю часть кода. В ней программе указывается, что если кто-нибудь хочет завершить программу через Ctrl+C, то содержимое сначала оборачивается, после чего выполняется. Эта ситуация хороша, если вы храните информацию в файле и хотите сбросить все в момент выхода.

Как послать Multipart-Encoded файл

Requests позволяет легко послать на сервер Multipart-Encoded файлы:

>>> url = 'http://httpbin.org/post' 
>>> files = {'file': open('report.xls', 'rb')}
>>> r = requests.post(url, files=files) 
>>> r.text 
{ ... "files": { "file": "<censored...binary...data>" }, ... }

Вы можете установить имя файла, content-type и заголовки в явном виде:

>>> url = 'http://httpbin.org/post' 
>>> files = {'file': ('report.xls', open('report.xls', 'rb'), 'application/vnd.ms-excel', {'Expires': '0'})}
>>> r = requests.post(url, files=files)
>>> r.text
{ ... "files": { "file": "<censored...binary...data>" }, ... }

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

>>> url = 'http://httpbin.org/post'
>>> files = {'file': ('report.csv', 'some,data,to,send\nanother,row,to,send\n')}
>>> r = requests.post(url, files=files)
>>> r.text
{ ... "files": { "file": "some,data,to,send\nanother,row,to,send\n" }, ... }

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

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

POST

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

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

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» данные, которые были переданы возвращаются в этом поле.

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

python3 rdemo.py

{‘established’: ‘2018’, ‘website’: ‘heihei.ru’}

Python requests reading a web page

The method issues a GET request; it fetches documents
identified by the given URL.

read_webpage.py

#!/usr/bin/env python3

import requests as req

resp = req.get("http://www.webcode.me")

print(resp.text)

The script grabs the content of the web page.

resp = req.get("http://www.webcode.me")

The method returns a response object.

print(resp.text)

The text attribute contains the content of the response, in Unicode.

$ ./read_webpage.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My html page</title>
</head>
<body>

    <p>
        Today is a beautiful day. We go swimming and fishing.
    </p>

    <p>
         Hello there. How are you?
    </p>

</body>
</html>

This is the output of the script.

The following program gets a small web page and strips its HTML tags.

strip_tags.py

#!/usr/bin/env python3

import requests as req
import re

resp = req.get("http://www.webcode.me")

content = resp.text

stripped = re.sub('<+?>', '', content)
print(stripped)

The script strips the HTML tags of the
web page.

stripped = re.sub('<+?>', '', content)

A simple regular expression is used to strip the HTML tags.

Parameter Values

Parameter Description
url Try it Required. The url of the request
data Try it Optional. A dictionary, list of tuples, bytes or a file object to send to the specified url
json Try it Optional. A JSON object to send to the specified url
files Try it Optional. A dictionary of files to send to the specified url
allow_redirects Try it Optional. A Boolean to enable/disable redirection.Default
(allowing redirects)
auth Try it Optional. A tuple to enable a certain HTTP authentication.Default

cert Try it Optional. A String or Tuple specifying a cert file or key.Default

cookies Try it Optional. A dictionary of cookies to send to the specified url.Default

headers Try it Optional. A dictionary of HTTP headers to send to the specified url.Default
proxies Try it Optional. A dictionary of the protocol to the proxy url.Default

stream Try it Optional. A Boolean indication if the response should be immediately downloaded (False) or streamed (True).Default

timeout Try it Optional. A number, or a tuple, indicating how many seconds to wait for the client to make a connection and/or send a response.Default which means the request will continue
until the connection is closed
verify Try it
Try it
Optional. A Boolean or a String indication to verify the servers TLS certificate or not.Default

Производительность

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

Время ожидания

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

По умолчанию, будет ждать ответа до бесконечности, поэтому вы почти всегда должны указывать время ожидания. Чтобы установить время ожидания, используйте параметр . Тайм-аут может быть целым числом или числом с плавающей запятой, представляющим количество секунд ожидания ответа:

В первом запросе, время ожидания истекает через одну секунду. Во втором — через 3,05 секунд.

Вы также можете передать кортеж тайм-ауту. Первый элемент в кортеже является тайм-аутом соединения (время, которое позволяет установить клиенту соединение с сервером), а второй элемент — время ожидания чтения (время ожидания ответа после того, как клиент установил соединение):

Если запрос устанавливает соединение в течение 2 секунд и получает данные в течение 5 секунд после установки соединения, то ответ будет возвращен. Если время ожидания истекло — функция вызовет исключение :

Ваша программа может перехватить исключение и ответить соответствующим образом.

Объект Session

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

Под этими абстракциями находится класс . Если вам необходимо настроить контроль над выполнением запросов и повысить производительность вашего приложения — вам может потребоваться использовать экземпляр напрямую.

Сеансы используются для сохранения параметров в запросах. Например, если вы хотите использовать одну и ту же аутентификацию для нескольких запросов, вы можете использовать сеанс:

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

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

Максимальное количество попыток

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

Транспортные адаптеры позволяют вам определять набор конфигураций для каждой службы , с которой вы взаимодействуете. Например, вы хотите, чтобы все запросы к https://api.github.com, повторялись по три раза, прежде чем вызовется исключение . Вы должны сконструировать транспортный адаптер, установить его параметр и подключить его к существующему сеансу:

Когда вы монтируете и в — будет придерживаться этой конфигурации в каждом запросе к https://api.github.com.

Время ожидания, транспортные адаптеры и сеансы, предназначены для обеспечения эффективности вашего кода и отказоустойчивости приложения.

What Are the Various Types of HTTP Request Methods?

GET

GET is used to retrieve and request data from a specified resource in a server. GET is one of the most popular HTTP request techniques. In simple words, the GET method is used to retrieve whatever information is identified by the Request-URL.

HEAD

The HEAD technique requests a reaction that is similar to that of GET request, but doesn’t have a message-body in the response. The HEAD request method is useful in recovering meta-data that is written according to the headers, without transferring the entire content. The technique is commonly used when testing hypertext links for accessibility, validity, and recent modification.

POST

Another popular HTTP request method is POST. In web communication, POST requests are utilized to send data to a server to create or update a resource.  The information submitted to the server with POST request method is archived in the request body of the HTTP request. The HTTP POST method is often used to send user-generated data to a server. One example is when a user uploads a profile photo.

PUT

PUT is similar to POST as it is used to send data to the server to create or update a resource. The difference between the two is that PUT requests are idempotent. This means that if you call the same PUT requests multiple times, the results will always be the same.

DELETE

Just as it sounds, the DELETE request method is used to delete resources indicated by a specific URL. Making a DELETE request will remove the targeted resource.

PATCH

A PATCH request is similar to POST and PUT. However, its primary purpose is to apply partial modifications to the resource. And just like a POST request, the PATCH request is also non-idempotent. Additionally, unlike POST and PUT which require a full user entity, with PATCH requests, you may only send the updated username.

TRACE

TRACE requests are used to invoke a remote, application loop-back test along the path to the target resource. The TRACE method allows clients to view whatever message is being received at the other end of the request chain so that they can use the information for testing or diagnostic functions.

CONNECT

The CONNECT request method is used by the client to create a network connection to a web server over a particular HTTP. A good example is SSL tunneling. In a nutshell, CONNECT request establishes a tunnel to the server identified by a specific URL.

Headers

Another thing you can get from the response are the headers. You can take a look at them by using the headers dictionary on the response object.

Headers are sent along with the request and returned in the response. Headers are used so both the client and the server know how to interpret the data that is being sent and received in the response/response.

We see the various headers that are returned. A lot of times you won’t need to use the header information directly, but it’s there if you need it.

The content type is usually the one you may need because it reveals the format of the data, for example HTML, JSON, PDF, text, etc. But the content type is normally handled by Requests so you can easily access the data that gets returned.

C# POST request with WebRequest

The next example creates a POST request with .

Program.cs

using System;
using System.IO;
using System.Text;
using System.Net;
using System.Text.Json;

var url = "https://httpbin.org/post";

var request = WebRequest.Create(url);
request.Method = "POST";

var user = new User("John Doe", "gardener");
var json = JsonSerializer.Serialize(user);
byte[] byteArray = Encoding.UTF8.GetBytes(json);

request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = byteArray.Length;

using var reqStream = request.GetRequestStream();
reqStream.Write(byteArray, 0, byteArray.Length);

using var response = request.GetResponse();
Console.WriteLine(((HttpWebResponse)response).StatusDescription);

using var respStream = response.GetResponseStream();

using var reader = new StreamReader(respStream);
string data = reader.ReadToEnd();
Console.WriteLine(data);

record User(string Name, string Occupation);

We send a POST request to the https://httpbin.org/post page. The data sent
is in JSON format.

var request = WebRequest.Create(url);
request.Method = "POST";

We set the method of the request to POST.

var user = new User("John Doe", "gardener");
var json = JsonSerializer.Serialize(user);
byte[] byteArray = Encoding.UTF8.GetBytes(json);

We serialize a user object to JSON and transform the JSON data into an array of
bytes.

using var reqStream = request.GetRequestStream();
reqstream.Write(byteArray, 0, byteArray.Length);

We get the stream of the request with and write
the byte array into the stream with .

using var response = request.GetResponse();

We get the response with .

Console.WriteLine(((HttpWebResponse)response).StatusDescription);

We print the status of the response.

using var respStream = response.GetResponseStream();

using var reader = new StreamReader(respStream);
string data = reader.ReadToEnd();
Console.WriteLine(data);

We read the data from the response stream.

$ dotnet run
OK
{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "{\"Name\":\"John Doe\",\"Occupation\":\"gardener\"}": ""
  }, 
  "headers": {
    "Content-Length": "43", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-5ffb119c-010dea546a9b4c8c370bca46"
  }, 
  "json": null, 
  "origin": "188.167.250.74", 
  "url": "https://httpbin.org/post"
}

Заголовки

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

script.py

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

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

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

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.

PHP POST request in Laravel

In the following example, we send a POST request from an HTML form.

resources/views/home.blade.php

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Home page</title>
        <style>
            .alert { color: red}
        </style>
    </head>
    <body>
        @if ($errors->any())
        <div class="alert">
            <ul>
                @foreach ($errors->all() as $error)
                    <li>{{ $error }}</li>
                @endforeach
            </ul>
        </div>
        @endif
         <form action="process_form" method="post">
            @csrf
            <label for="name">Name</label> <input id="name" 
                value="{{old('name')}}"type="text" name="name">
            <label for="message">Message</label> <input id="message" 
                value="{{old('message')}}" type="text" name="message">
            <button type="submit">Submit</button>
        </form>
    </body>
</html>

We have a POST form in a Blade template. Laravel requires CSRF protection for
POST requests. We enable CSRF protection with .

routes/web.php

<?php

use Illuminate\Support\Facades\Route;
use Illuminate\Http\Request;

Route::get('/', function () {
    return view('home');
});


Route::post('/process_form', function (Request $request) {

    $request->validate();
    
    $name = $request->input('name');
    $message = $request->input('message');
    
    $output = "$name says: $message";

    return $output;
});

We validate and retrieve the POST parameters and send them in the response.
This example should be tested in a browser.

In this tutorial, we have worked with GET and POST requests in plain PHP,
Symfony, Slim, and Laravel.

List tutorials.

Асинхронность

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

Начиная с версии 3.5, Python предлагает асинхронность внутри своего ядра, используя aiohttp. Библиотека aiohttp предоставляет асинхронный HTTP-клиент, построенный поверх asyncio. Эта библиотека позволяет отправлять запросы последовательно, но не дожидаясь первого ответа, прежде чем отправлять новый. В отличие от конвейерной передачи HTTP, aiohttp отправляет запросы по нескольким соединениям параллельно, избегая проблемы, описанной ранее.

Использование aiohttp

import aiohttp
import asyncio

async def get(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            return response

loop = asyncio.get_event_loop()

coroutines = [get("http://example.com") for _ in range(8)]

results = loop.run_until_complete(asyncio.gather(*coroutines))

print("Results: %s" % results)

Все эти решения (с использованием Session, thread, futures или asyncio) предлагают разные подходы к ускорению работы HTTP-клиентов. Но какая между ними разница с точки зрения производительности?

Эффективная обработка файлов

Одна из функций парсера – это хранение данных как в базе данных, так и в обычных файлах, таких как CSV/Text. Если собираете большой объем данных, это не означает, что операция ввода-вывода будет в цикле. Давайте рассмотрим, как это делается.

Пробуем:

Python

try:
a_list_variable = []
a_list_variable.extend(a_func_return_record())
except requests.ConnectionError as e:
print(«Упс!! Ошибка подключения к интернету.»)
print(str(e))
except requests.Timeout as e:
print(«Упс!! Время ожидания истекло.»)
print(str(e))
except requests.RequestException as e:
print(«Упс!! Возникла непредвиденная ошибка!»)
print(str(e))
except KeyboardInterrupt:
print(«Кто-то закрыл принудительно программу.»)
finally:
print(«Total Records = » + str(len(property_urls)))
try:
# файл для хранения URL
record_file = open(‘records_file.txt’, ‘a+’)
record_file.write(«\n».join(property_urls))
record_file.close()
except Exception as ex:
print(«Возникла ошибка при сохранении данных, текст ошибки:»)
print(str(e))

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

try

a_list_variable=

a_list_variable.extend(a_func_return_record())

exceptrequests.ConnectionError ase

print(«Упс!! Ошибка подключения к интернету.»)

print(str(e))

exceptrequests.Timeout ase

print(«Упс!! Время ожидания истекло.»)

print(str(e))

exceptrequests.RequestException ase

print(«Упс!! Возникла непредвиденная ошибка!»)

print(str(e))

exceptKeyboardInterrupt

print(«Кто-то закрыл принудительно программу.»)

finally

print(«Total Records  = «+str(len(property_urls)))

try

# файл для хранения URL

record_file=open(‘records_file.txt’,’a+’)

record_file.write(«\n».join(property_urls))

record_file.close()

exceptExceptionasex

print(«Возникла ошибка при сохранении данных, текст ошибки:»)

print(str(e))

Здесь я вызываю функцию (хотя вы не обязаны делать то же самое), которая добавляет записи в список. Как только это будет сделано, или программа будет остановлена, перед завершением она просто сохранит весь список в файл за раз. Намного лучше, чем несколько операций ввода-вывода

Надеюсь, эта статья была для вас полезной. Пожалуйста, Поделитесь своим опытом о том, как сделать парсер более эффективным!

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

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

Adblock
detector