Лучшие HTTP-клиенты Python для веб-парсинга

Откройте для себя лучшие HTTP-клиенты Python, их функции и лучшие варианты использования для веб-парсинга в 2024 году.
4 min read
Best Python HTTP Clients blog image

HTTP-клиенты — это полезные библиотеки Python, которые позволяют коду отправлять запросы на веб-серверы или в API и получать ответы. Они дают возможность легко отправлять различные типы HTTP-запросов (GET, POST, PUT, DELETE и т. д.), получать и отправлять данные, а также выполнять действия на веб-сайтах или в API.

В области веб-парсинга эти клиенты часто используются вместе с библиотеками HTML-парсинга, такими как Beautiful Soup или html5lib.

В этой статье вы рассмотрим некоторые из лучших HTTP-клиентов Python, включая Requests, urllib3, Uplink, GRequests, HTTPX и aiohttp. Вы оцените каждый из них на основе их функций, простоты использования, документации и поддержки, а также популярности. Прочитав эту статью, вы лучше поймете, какая библиотека наиболее подходит для вашего сценария использования.

Requests

Давайте начнем с самого популярного HTTP-клиента Python — библиотеки Requests с ее впечатляющим показателем с 30 миллионами загрузок в неделю.

Вот пример того, как можно обрабатывать HTTP-запросы и ответы с помощью Requests:

import requests

print("Testing `requests` library...")
resp = requests.get('https://httpbin.org/get', params={"foo": "bar"})
if resp.status_code == 200:     # success
    print(f"Response Text: {resp.text} (HTTP-{resp.status_code})")
else:   # error
    print(f"Error: HTTP-{resp.status_code}")

Обратите внимание, что httpbin.org дает примеры ответов для тестирования различных HTTP-методов.

В этом фрагменте кода метод requests.get(...) принимает нужный URL-адрес и один параметр запроса foo. Вы можете передать любые параметры запроса, используя аргумент params.

При использовании Requests и других HTTP-клиентов вам не нужно вручную добавлять строки запросов к URL-адресам или кодировать данные, поскольку библиотека сделает это за вас. Чтобы отправить данные JSON, вы передаете словарь Python с использованием аргумента data, а ответ JSON можно получить непосредственно с помощью resp.json().

Библиотека Requests по умолчанию автоматически обрабатывает HTTP-перенаправления (3xx), что удобно при веб-парсинге для доступа к содержимому перенаправленных URL-адресов. Она также поддерживает соединения по протоколу SSL.

Внутри Requests средство urllib3 используется для управления низкоуровневыми HTTP-задачами, такими как объединение соединений и проверка SSL, а разработчикам предлагается более продвинутый Pythonic API.

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

Библиотека Requests также поддерживает потоковую передачу данных, что полезно для выполнения задач веб-парсинга, требующих ответов большого объема, таких как загрузка файлов или обработка потоковых данных из API.

Чтобы эффективно обрабатывать данные ответа без загрузки их в память, вы можете использовать такие методы, как iter_content() или iter_lines():

import requests

print("Testing `requests` library with streaming...")
resp = requests.get('https://httpbin.org/stream/10', stream=True)
for chunk in resp.iter_content(chunk_size=1024):
    print(chunk.decode('utf-8'))

Однако в библиотеке Requests отсутствуют встроенные асинхронные возможности и поддержка кэширования (хотя она доступна через requests-cache). Кроме того, Requests не поддерживает HTTP/2, который вряд ли будет добавлен в ближайшее время, как указано в этой дискуссии.

Примечание: HTTP/2 — это новая версия протокола HTTP, разработанная для того, чтобы быть быстрее и эффективнее HTTP/1.1. Этот протокол позволяет отправлять множество запросов и ответов по одному соединению по протоколу управления передачей данных (TCP) посредством мультиплексирования, что приводит к сокращению числа подключений типа «клиент-сервер» и ускоряет загрузку страниц. Однако поддержка HTTP/2 по-прежнему предоставляется в ограниченном объеме.

Библиотека Requests упрощает HTTP-взаимодействия Python. Она отличается простотой методов, лаконичным синтаксисом, автоматическим объединением соединений для повышения эффективности и встроенным декодированием JSON. Простота использования, управление сеансами, возможности потоковой передачи данных и обширная документация  обесловили ее популярность среди разработчиков.

urllib3

urllib3 — это хорошо протестированная и широко используемая библиотека для выполнения HTTP-запросов не только разработчиками, но и многими другими HTTP-клиентами. Она предлагает полезные функции и возможности настройки для обработки низкоуровневых HTTP-запросов при веб-парсинге.

Вот простейший пример использования urllib3 для HTTP-запроса:

import urllib3

print("Testing `urllib3` library...")
http = urllib3.PoolManager()    # PoolManager for connection pooling
resp = http.request('GET', 'https://httpbin.org/get', fields={"foo": "bar"})

if resp.status == 200:     # success
    print(f"Response: {resp.data.decode('utf-8')} (HTTP-{resp.status})")
else:    # error
    print(f"Error: HTTP-{resp.status}")

В этом фрагменте кода urllib3.poolManager() создает пул подключений, которые можно повторно использовать для нескольких запросов, повышая производительность, избегая лишних расходов на установку новых подключений для каждого запроса. Вместе с URL-адресом вы можете передать необходимые параметры запроса, используя аргумент fields .

Одной из примечательных особенностей urllib3 является способность получать потоковые ответы, что позволяет эффективно обрабатывать большие объемы данных без загрузки их в память. Это полезно для загрузки больших файлов или использования потоковых API во время веб-парсинга.

urllib3 по умолчанию поддерживает автоматическое перенаправление и имеет встроенную поддержку SSL. Однако в нем отсутствуют встроенные асинхронные функции, поддержка кэширования и управления сеансами (например, файлы cookie), а также HTTP/2.

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

Если вам нужна мощная библиотека и вам не нужно управлять сеансами, urllib3 отлично подходит для простых задач по веб-парсингу.

Uplink

Uplink — мощный, но менее известный HTTP-клиент Python. Он упрощает взаимодействие с API-интерфейсами RESTful с использованием интерфейсов на основе классов, что делает его особенно полезным для веб-парсинга, включающего вызовы API.

Взгляните на этот пример кода, использующего Uplink для вызова конечной точки API:

import uplink

@uplink.json
class JSONPlaceholderAPI(uplink.Consumer):
    @uplink.get("/posts/{post_id}")
    def get_post(self, post_id):
        pass


def demo_uplink():
    print("Testing `uplink` library...")
    api = JSONPlaceholderAPI(base_url="https://jsonplaceholder.typicode.com")
    resp = api.get_post(post_id=1)
    if resp.status_code == 200:     # success
        print(f"Response: {resp.json()} (HTTP-{resp.status_code})")
    else:   # error
        print(f"Error:HTTP-{resp.status_code}")

Этот фрагмент кода определяет класс JSONPlaceHolderAPI , унаследованный от uplink.Consumer. Он использует декоратор @uplink.get  для создания HTTP-запроса GET для API JSONPlaceHolder с целью получения определенного сообщения. Параметр post_id динамически включается в конечную точку с помощью декоратора @uplink.get ("/posts/{post_id}"). Сайт https://jsonplaceholder.typicode.com имитирует REST API, предоставляя ответы JSON для тестирования и разработки.

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

Однако в Uplink нет встроенной поддержки потоковых ответов, асинхронных запросов, кэширования (хотя может использоваться кэш запросов requests-cache) и HTTP/2.

Uplink предоставляет достаточную документацию по своим мощным функциям, но она поддерживается неактивно (последняя версия 0.9.7 была выпущена в марте 2022 года) и не очень популярна. Хотя подход, основанный на классах, и синтаксис декоратора могут понравиться объектно-ориентированным разработчикам, он обеспечивает лишь умеренную простоту использования для тех, кто предпочитает скриптовый стиль Python.

Пользователи обычно выбирают Uplink, когда им нужно собирать данные в основном с разных конечных точек RESTful API, а не с HTML-страниц.

GRequests

GRequests — это расширение известной библиотеки Requests, добавляющее поддержку асинхронных запросов. Оно позволяет одновременно получать данные с нескольких веб-сайтов или из нескольких API.

В отличие от использования последовательных запросов, при котором очередной запрос отправляется после получения ответа на предыдущий, GRequests может одновременно отправлять несколько запросов, повышая тем самым эффективность работы. Это особенно полезно для получения данных со множества веб-сайтов или из множества API.

Взгляните на этот пример:

import grequests

print("Testing `grequests` library...")
# Fetching data from multiple URLs
urls = [
    'https://www.python.org/',
    'http://httpbin.org/get',
    'http://httpbin.org/ip',
]

responses = grequests.map((grequests.get(url) for url in urls))
for resp in responses:
    print(f"Response for: {resp.url} ==> HTTP-{resp.status_code}")

В этом коде GRequests одновременно отправляет три запроса GET с помощью grequests.map(...) на разные URL-адреса и собирает ответы в список с именем responses. Затем этот инструмент выполняет итерацию этих ответов и выводит их. В GRequests встроена сетевая библиотека gevent на основе сопрограмм, которая используется для отправки асинхронных HTTP-запросов. Она позволяет отправлять несколько HTTP-запросов одновременно, не управляя сложным параллелизмом. Одним из практических применений этого может быть поиск новостей на разных веб-сайтах по определенной теме или категории.

GRequests также поддерживает такие функции, как автоматическая обработка перенаправлений, поддержка SSL и обработка потоковых ответов без одновременной загрузки их всех в память. Однако имейте в виду, что GRequests не имеет встроенной поддержки HTTP/2 или возможностей кэширования, хотя может использовать requests-cache.

GRequests упрощает асинхронные HTTP-запросы с помощью интуитивно понятных методов, аналогичных базовой библиотеке Requests. Это устраняет необходимость в сложных конструкциях async/await для обработки параллелизма, что упрощает использование. Однако документация является минимальной из-за небольшой кодовой базы (213 строк в версии 0.7.0) и снижения активности разработчиков. Эти факторы способствуют снижению популярности данного инструмента.

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

HTTPX

HTTPX — это современный и многофункциональный HTTP-клиент для Python, широко используемый во всех типах проектов по веб-парсингу. Он призван заменить Python-библиотеку Requests, обеспечивая асинхронную поддержку и повышенную производительность.

Следующий пример демонстрирует асинхронный HTTP-запрос GET с использованием HTTPX:

import httpx
import asyncio

async def fetch_posts():
    async with httpx.AsyncClient() as client:
        response = await client.get('https://jsonplaceholder.typicode.com/posts')
        return response.json()

async def httpx_demo():
    print("Testing `httpx` library...")
    posts = await fetch_posts()
    for idx, post in enumerate(posts):
        print(f"Post #{idx+1}: {post['title']}")

# async entry point to execute the code
asyncio.run(httpx_demo())

Этот код определяет асинхронную функцию fetch_posts (), которая извлекает фиктивные сообщения в блоге из API https://jsonplaceholder.typicode.com/posts с помощью httpx.AsyncClient(). Другая асинхронная функция, httpx_demo(), ожидает, пока fetch_posts() вернет эти сообщения, а затем выводит их заголовки в цикле. Наконец, asyncio.run(httpx_demo()) служит точкой входа для асинхронного выполнения httpx_demo().

Помимо встроенной поддержки асинхронных HTTP-клиентов, HTTPX также предлагает встроенную поддержку HTTP/2. Это позволяет быстрее загружать несколько ресурсов одновременно через одно TCP-соединение, что затрудняет веб-сайтам отслеживание отпечатков вашего браузера во время просмотра веб-страниц.

Чтобы отправить запрос HTTP/2, просто задайте параметр http2=True при создании клиента HTTPX:

import httpx

client = httpx.Client(http2=True)
response = client.get("https://http2.github.io/")
print(response)

Имейте в виду, что для использования HTTP/2 вам необходимо установить HTTPX с поддержкой http2:

pip install httpx[http2]

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

Вот пример потокового текстового ответа с использованием HTTPX:

with httpx.stream("GET", "https://httpbin.org/stream/10") as resp:
   for text in resp.iter_text():
       print(text)

Хотя HTTPX не имеет встроенных возможностей кэширования, вместо этого вы можете использовать Hishel.

HTTPX по умолчанию не следует перенаправлениям HTTP, но вы можете включить это с помощью параметра follow_redirects:

import httpx

# test http --> https redirect
response = httpx.get('http://github.com/', follow_redirects=True)

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

Если вы ищете многофункциональный асинхронный HTTP-клиент, обратите внимание на HTTPX.

aiohttp

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

Вот пример применения aiohttp для одновременного парсинга нескольких URL-адресов:

import asyncio
import aiohttp

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

async def demo_aiohttp():
    print("Testing `aiohttp` library...")
    urls = [
        'https://www.python.org/',
        'http://httpbin.org/get',
        'http://httpbin.org/ip',
    ]
    tasks = [fetch_data(url) for url in urls]
    responses = await asyncio.gather(*tasks)
    for resp_text in responses:
        print(f"Response: {resp_text}")

# async entry point to execute the code      
asyncio.run(demo_aiohttp())

Асинхронная функция fetch_data(...) создает aiohttp.ClientSession() и отправляет запрос GET на указанный URL-адрес. Затем она формирует список задач для каждого URL-адреса и выполняет их одновременно с asyncio.gather(...). После выполнения всех задач собранные данные (в данном случае текст ответа) собираются и распечатываются. Фактическое выполнение начинается с помощью asyncio.run(demo_aiohttp()).

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

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

Однако aiohttp не поддерживает HTTP/2 и встроенные возможности кэширования. Тем не менее, при необходимости, вы можете интегрировать кэширование с помощью таких библиотек, как aiohttp-client-cache.

aiohttp может быть сложнее в использовании, чем простые HTTP-клиенты, такие как Requests, особенно для новичков. Его асинхронный характер и дополнительные функции требуют хорошего понимания асинхронного программирования на Python. Однако он довольно популярен: на GitHub он получил 14,7 тысяч звезд, а на его основе создано множество сторонних библиотек . aiohttp также предлагает разработчикам исчерпывающую документацию.

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

Ознакомьтесь со следующей таблицей с кратким обзором лучших HTTP-клиентов Python:

Requests urllib3 Uplink GRequests HTTPX aiohttp
Простота использования Простой Легко модерируется Умеренно сложный Простой Умеренно сложный Умеренно сложный
Автоматические перенаправления Да Да Да Да Требуется включить Да
Поддержка SSL Да Да Да Да Да Да
Поддержка асинхронности Нет Нет Нет Да Да Да
Потоковые ответы Да Да Нет Да Да Да
Поддержка HTTP/2 Нет Нет Нет Нет Да Нет
Поддержка кэширования Через: кэш запросов Нет Через: кэш запросов Через: кэш запросов Через: Hishel Через: aiohttp-client-cache

Заключение

Из этой статьи вы узнали все о нескольких популярных HTTP-клиентах Python, включая Requests, urllib3, Uplink, GRequests, HTTPX и aiohttp, каждый из которых обладает уникальными особенностями, такими как простота, поддержка асинхронности, потоковая передача и HTTP/2.

В то время как Requests, Uplink и GRequests известны своей простотой, aiohttp и HTTPX предлагают мощные асинхронные возможности. Хотя Requests остается самым популярным решением, aiohttp и HTTPX набирают популярность благодаря асинхронным возможностям. В конечном итоге вам нужно будет изучить каждое из этих решений, чтобы выбрать то, которое отвечает вашим потребностям.

При реальном веб-парсинге вам нужно подумать не только о том, какой HTTP-клиент использовать, но и как обойти меры по борьбе с ботами и задействовать прокси-серверы. К счастью, с этим вам может помочь Bright Data.

Bright Data упрощает веб-парсинг с помощью таких инструментов, как Web Scraper IDE, который предлагает готовые функции и шаблоны JavaScript, и Web Unlocker, обеспечивающий обход капч и мер по борьбе с ботами. Scraping Browser от Bright Data интегрируется с Puppeteer, Playwright и Selenium для многоэтапного сбора данных. Кроме того, прокси-сети и сервисы Bright Data обеспечивают доступ из разных мест. Эти инструменты решают сложные задачи, такие как управление прокси-серверами и разгадывание капч, поэтому вы можете сосредоточиться на получении необходимых данных.

Начните бесплатное опробование сегодня и ознакомьтесь со всеми возможностями Bright Data.

Кредитная карта не требуется