Requests vs. HTTPX vs. AIOHTTP: Detaillierter Vergleich

Entdecken Sie Requests, HTTPX und AIOHTTP, die beliebtesten HTTP-Clients von Python und finden Sie die richtige Lösung für Ihre Anforderungen im Bereich der Datenerfassung.
12 min read
Requests vs. HTTPX vs. AIOHTTP blog image

Python verfügt über eine große Auswahl an HTTP-Clients. Für diejenigen von Ihnen, die mit HTTP (Hypertext Transfer Protocol) nicht vertraut sind, handelt es sich um das Grundgerüst des gesamten Webs.

Heute wollen wir drei der beliebtesten HTTP-Clients von Python miteinander vergleichen: Requests, HTTPX und AIOHTTP. Wenn Sie mehr über die anderen verfügbaren Clients erfahren möchten, finden Sie hier einen Überblick.

Kurzübersicht

Requests ist der standardmäßige HTTP-Client von Python. Er verwendet blockierende und synchrone Vorgänge zur einfachen Verwendung. Bei HTTPX handelt es sich um einen neueren asynchronen Client, der sowohl auf Geschwindigkeit als auch auf Benutzerfreundlichkeit ausgelegt ist. AIOHTTP gibt es bereits seit über einem Jahrzehnt. Er gehört zu den ersten und am besten unterstützten asynchronen HTTP-Clients, die Python zu bieten hat.

Funktion Requests HTTPX AIOHTTP
Struktur Synchronisierung/Blockierung Asynchron/nicht-blockierend Asynchron/nicht-blockierend
Sessions Ja Ja Ja
Gleichzeitigkeit Nein Ja Ja
HTTP/2-Unterstützung Nein Ja Ja
Leistung Niedrig Hoch Hoch
Wiederholungen Automatisch Automatisch Manuell
Timeout-Unterstützung Pro Anfrage Vollständige Unterstützung Vollständige Unterstützung
Proxy-Unterstützung Ja Ja Ja
Benutzerfreundlichkeit Einfach Schwierig Schwierig
Anwendungsfälle Einfache Projekte/Prototyping Hochleistung Hochleistung

Python Requests

Python Requests ist äußerst intuitiv und nutzerfreundlich. Wenn Sie keine Spitzenleistung benötigen, ist dieser Client die erste Wahl zur Erstellung von HTTP-Anfragen in Python. Er wird weithin verwendet, ist einfach zu bedienen und der am besten dokumentierte Python-HTTP-Client der Welt.

Sie können ihn mit dem nachstehenden Befehl installieren.

Installation

pip install requests

Requests unterstützt das Standard-HTTP-Protokoll und verfügt über Funktionen zur Session-Verwaltung. Mit Sessions können Sie eine dauerhafte Verbindung zu einem Server herstellen. Auf diese Weise lassen sich Ihre Daten viel schneller und effizienter abrufen, als bei einzelnen Anfragen. Falls Sie nur einfache Anfragen (GET, POST, PUT und DELETE) stellen möchten und es Ihnen nicht unbedingt auf hohe Leistung ankommt, dann genügt die Requests-Bibliothek all Ihren HTTP-Anforderungen.

Anleitungen zur Proxy-Integration, zu User-Agents und zu jeder Menge anderer Dinge sind überall im Web zu finden.

Nachstehend finden Sie einige grundlegende Anwendungsbeispiele.

import requests

# make a simple request
response = requests.get("https://jsonplaceholder.typicode.com/posts")
print(response.status_code)

# use a session for multiple requests to the same server
with requests.Session() as client:
    for get_request in range(1000):
        response = client.get("https://jsonplaceholder.typicode.com/posts")
        print(response.status_code)

Requests ist bei asynchronen Vorgängen unzureichend. Mit der asynchronen Unterstützung lassen sich mehrere Anfragen gleichzeitig stellen. Anschließend können Sie alle abwarten. Bei synchronen Anfragen ist jeweils nur eine Anfrage möglich und Sie müssen auf eine Antwort des Servers warten, bevor Sie eine weitere Anfrage stellen können. Falls Ihr Programm viele HTTP-Anfragen stellen muss, schränkt die Verwendung von Requests Ihren Code in gewisser Weise ein.

HTTPX

HTTPX ist die neueste und modernste dieser drei Bibliotheken. Sie unterstützt standardmäßig sämtliche asynchronen Vorgänge. Dennoch hat sie eine benutzerfreundliche und intuitive Syntax. Setzen Sie HTTPX ein, wenn Requests nicht ausreicht und Sie die Leistung ohne allzu großen Lernaufwand steigern müssen.

Mit asyncio (asynchrone Ein- und Ausgabe) können Sie Code schreiben, der asynchrone Antworten mit dem Schlüsselwort await vollständig ausnutzen. Dadurch können wir unsere Vorgänge fortsetzen, ohne alles andere im Code zu blockieren, während wir auf das Geschehen der Dinge ausharren. Dank dieser asynchronen Vorgänge lassen sich große Mengen von Anfragen stellen. Anstatt jeweils eine Anfrage zu stellen, können Sie 5, 50 oder sogar 100 Anfragen stellen!

Installation

pip install httpx

Hier sind einige Beispiele für den Einstieg in HTTPX.

import httpx
import asyncio

# synchronous response
response = httpx.get("https://jsonplaceholder.typicode.com/posts")
print(response.status_code)

# basic async session usage
async def main():
    async with httpx.AsyncClient() as client:
        for get_request in range(1000):
            response = await client.get("https://jsonplaceholder.typicode.com/posts")
            print(response.status_code)
asyncio.run(main())

HTTPX ist zwar eine ausgezeichnete Wahl, um neuen Code zu schreiben, bringt aber einige Einschränkungen mit sich. Aufgrund seiner Syntax kann es sich als schwierig erweisen, Ihre bestehende Requests-Codebasis durch HTTPX zu ersetzen. eim Schreiben von asynchronem Code sind einige Textbausteine erforderlich, und solange Sie nicht Tausende von Anfragen stellen, lohnt sich der zusätzliche Zeitaufwand bei der Entwicklung meistens überhaupt nicht.

Im Vergleich zu AIOHTTP (wie Sie gleich erfahren werden) ist HTTPX nicht annähernd so schnell. Sollten Sie einen Web-Server oder ein komplexes Netzwerk aufbauen wollen, ist HTTPX aufgrund seines noch unreifen Ökosystems nicht die geeignete Wahl. HTTPX eignet sich am besten für neue, client-seitige Anwendungen mit modernen Funktionen wie HTTP/2.

AIOHTTP

Bei der asynchronen Programmierung wird AIOHTTP schon seit langem in Python verwendet. Unabhängig davon, ob Sie einen Server, eine client-seitige Anwendung oder ein verteiltes Netzwerk betreiben, AIOHTTP deckt all diese Anforderungen ab. Doch von den drei Lösungen (Requests, HTTPX und AIOHTTP) hat AIOHTTP die steilste Lernkurve.

Wir beschränken uns auf die einfache Nutzung der Client-Seite, deshalb werden wir nicht allzu tief in die Trickkiste von AIOHTTP greifen. Wie HTTPX können wir mit AIOHTTP stapelweise Anfragen stellen. Im Gegensatz zu HTTPX unterstützt AIOHTTP jedoch keine synchronen Anfragen. Stellen Sie nur nicht zu viele auf einmal … Sie wollen ja nicht vom Server gesperrt werden.

Installation

pip install aiohttp

Schauen Sie sich die Grundfunktionen im Folgenden an.

import aiohttp
import asyncio

# make a single request
async def main():
    async with aiohttp.ClientSession() as client:
        response = await client.get("https://jsonplaceholder.typicode.com/posts")
        print(response)
        
asyncio.run(main())


# basic async session usage
async def main():
    with aiohttp.ClientSession() as client:
        for response in range(1000):
            response = await client.get("https://jsonplaceholder.typicode.com/posts")
            print(response)
            
asyncio.run(main())

AIOHTTP ist strikt asynchron. Wie Sie im obigen Code sehen können, benötigt unser Beispiel für eine einzige Anfrage weitaus mehr Code als eines unserer ersten beiden Beispiele. Unabhängig davon, wie viele Anfragen wir stellen wollen, müssen wir eine asynchrone Session einrichten. Deshalb empfiehlt es sich, Proxys mit AIOHTTP zu kombinieren. Bei einer einzigen Anfrage wäre das definitiv zu viel des Guten.

Trotz seiner vielen Stärken wird AIOHTTP Python Requests nicht vollständig ersetzen, es sei denn, Sie müssen viele ein- und ausgehende Anfragen auf einmal verarbeiten. In diesem Fall wird es die Leistung deutlich steigern. Verwenden Sie AIOHTTP, wenn Sie komplexe Anwendungen erstellen und eine blitzschnelle Kommunikation erfordern. Diese Bibliothek empfiehlt sich für Server, verteilte Netzwerke und hochkomplexe Web-Scraping-Anwendungen.

Leistungsvergleich

Nun werden wir mit jeder Bibliothek ein kleines Programm erstellen. Die Voraussetzungen sind denkbar einfach: Öffnen Sie eine Client-Session und stellen Sie 1000 API-Anfragen.

Zunächst müssen wir unsere Session mit dem Server erstellen. Als Nächstes stellen wir 1000 Anfragen. Wir werden zwei Arrays anlegen: eines für positive Antworten und eines für negative Antworten. Sobald der Vorgang abgeschlossen ist, geben wir die Gesamtzahl der positiven und negativen Anfragen aus. Wenn wir positive und negative Anfragen erhalten haben, geben wir deren Statuscodes auf der Konsole aus.

Bei unseren asynchronen Beispielen (HTTPX und AIOHTTP) nutzen wir eine chunkify()-Funktion. Diese wird zur Aufteilung eines Arrays in Chunks eingesetzt. Anschließend führen wir die Anfragen in Stapeln aus. Wollen wir zum Beispiel unsere Anfragen in Stapeln von 50 Anfragen ausführen, verwenden wir chunkify(), um den Stapel zu erstellen, und process_chunk(), um alle 50 Anfragen auf einmal auszuführen.

Werfen Sie einen Blick auf die nachfolgenden Funktionen.

def chunkify(iterable, size):
    iterator = iter(iterable)
    while chunk := list(islice(iterator, size)):
        yield chunk
        
        
async def process_chunk(client, urls, retries=3):
    tasks = [fetch(client, url, retries) for url in urls]
    return await asyncio.gather(*tasks)

Requests

Hier ist unser Code mit Requests. Dieser Code ist verglichen mit den beiden asynchronen Beispielen, die wir später verwenden, recht einfach. Wir öffnen eine Session und verwenden eine for-Schleife, um durch die Anfragen zu iterieren.

import requests
import json
from datetime import datetime

start_time = datetime.now()
good_responses = []
bad_responses = []

with requests.Session() as client:

    for get_request in range(1000):
        response = client.get("https://jsonplaceholder.typicode.com/posts")
        status_code = response.status_code
        if status_code  == 200:
            good_responses.append(status_code)
        else:
            bad_responses.append(status_code)

end_time = datetime.now()

print("----------------Requests------------------")
print(f"Time elapsed: {end_time - start_time}")
print(f"Good Responses: {len(good_responses)}")
print(f"Bad Responses: {len(bad_responses)}")

for status_code in set(bad_responses):
    print(status_code)
Ergebnisse von Python Requests

Requests hat die Aufgabe für uns in etwas mehr als 51 Sekunden erledigt. Dies entspricht etwa 20 Anfragen pro Sekunde. Ohne Verwendung einer Session müssen Sie mit 2 Sekunden pro Anfrage rechnen. Das ist ziemlich leistungsstark.

HTTPX

Hier der Code für HTTPX. Wie bereits erwähnt, verwenden wir chunkify() und process_chunk().

import httpx
import asyncio
from datetime import datetime
from itertools import islice

def chunkify(iterable, size):
    iterator = iter(iterable)
    while chunk := list(islice(iterator, size)):
        yield chunk

async def fetch(client, url, retries=3):
    """Fetch a URL with retries."""
    for attempt in range(retries):
        try:
            response = await client.get(url)
            return response.status_code
        except httpx.RequestError as e:
            if attempt < retries - 1:
                await asyncio.sleep(1)
            else:
                return f"Error: {e}"

async def process_chunk(client, urls, retries=3):
    tasks = [fetch(client, url, retries) for url in urls]
    return await asyncio.gather(*tasks)

async def main():
    url = "https://jsonplaceholder.typicode.com/posts"
    total_requests = 1000
    chunk_size = 50

    good_responses = []
    bad_responses = []

    async with httpx.AsyncClient(timeout=10) as client:
        start_time = datetime.now()

        urls = [url] * total_requests
        for chunk in chunkify(urls, chunk_size):
            results = await process_chunk(client, chunk)
            for status in results:
                if isinstance(status, int) and status == 200:
                    good_responses.append(status)
                else:
                    bad_responses.append(status)

        end_time = datetime.now()

        print("----------------HTTPX------------------")
        print(f"Time elapsed: {end_time - start_time}")
        print(f"Good Responses: {len(good_responses)}")
        print(f"Bad Responses: {len(bad_responses)}")

        if bad_responses:
            print("Bad Status Codes or Errors:")
            for error in set(bad_responses):
                print(error)

asyncio.run(main())

Hier unsere Ausgabe unter Verwendung von HTTPX. Im Vergleich zu Requests ist dies überwältigend. Die Gesamtdauer betrug knapp über 7 Sekunden. Das entspricht 139,47 Anfragen pro Sekunde. HTTPX brachte uns also ungefähr das 7-fache der Leistung von Requests.

Ergebnisse von HTTPX

AIOHTTP

Nun führen wir das Ganze nochmals unter Verwendung von AIOHTTP durch. Wir folgen der gleichen Grundstruktur wie beim HTTPX-Beispiel. Der einzig große Unterschied besteht darin, dass hier der AIOHTTP-Client den HTTPX-Client ersetzt.

import aiohttp
import asyncio
from datetime import datetime
from itertools import islice

def chunkify(iterable, size):
    iterator = iter(iterable)
    while chunk := list(islice(iterator, size)):
        yield chunk

async def fetch(session, url, retries=3):
    for attempt in range(retries):
        try:
            async with session.get(url) as response:
                return response.status
        except aiohttp.ClientError as e:
            if attempt < retries - 1:
                await asyncio.sleep(1)
            else:
                return f"Error: {e}"

async def process_chunk(session, urls):
    tasks = [fetch(session, url) for url in urls]
    return await asyncio.gather(*tasks)

async def main():
    url = "https://jsonplaceholder.typicode.com/posts"
    total_requests = 1000
    chunk_size = 50

    good_responses = []
    bad_responses = []

    async with aiohttp.ClientSession() as session:
        start_time = datetime.now()

        urls = [url] * total_requests
        for chunk in chunkify(urls, chunk_size):
            results = await process_chunk(session, chunk)
            for status in results:
                if isinstance(status, int) and status == 200:
                    good_responses.append(status)
                else:
                    bad_responses.append(status)

        end_time = datetime.now()

        print("----------------AIOHTTP------------------")
        print(f"Time elapsed: {end_time - start_time}")
        print(f"Good Responses: {len(good_responses)}")
        print(f"Bad Responses: {len(bad_responses)}")

        if bad_responses:
            print("Bad Status Codes or Errors:")
            for error in set(bad_responses):
                print(error)

asyncio.run(main())

AIOHTTP war mit gerade einmal etwas mehr als 4 Sekunden extrem schnell. Dieser HTTP-Client erzeugte über 241 Anfragen pro Sekunde! AIOHTTP ist etwa 10 Mal schneller als Requests und nahezu 50 % schneller als HTTPX. In Python ist AIOHTTP in Sachen Leistung eine Klasse für sich.

Ergebnisse von AIOHTTP

Was die Produkte von Bright Data leisten können

Bright Data bietet eine breite Auswahl an Lösungen, die Ihre HTTP-Client-basierten Arbeitsabläufe optimieren können, insbesondere für datenintensive Vorgänge wie Web-Scraping, API-Anfragen und Hochleistungsintegrationen. Im Folgenden sehen Sie, wie jedes Produkt eingesetzt wird:

  • Privatanwender-Proxys – Mit den Privatanwender-Proxys von Bright Data können Sie beim Scraping von Websites mit Python-HTTP-Clients wie AIOHTTP oder HTTPX Blockaden und Verbote umgehen. Diese Proxys ahmen das Verhalten echter Nutzer nach und gewähren so problemlos Zugriff auf geografisch eingeschränkte oder dynamische Inhalte.
  • Web-Scraper-APIs – Anstatt eine eigene Scraping-Infrastruktur zu schaffen und zu warten, bieten die Web-Scraper-APIs von Bright Data einen vorkonfigurierten Zugang zu Hunderten von beliebten Websites. Auf diese Weise können Sie sich auf die Datenanalyse konzentrieren, anstatt sich um Anfragen, Wiederholungsversuche oder Verbote sorgen zu müssen. Nutzen Sie einfach einen API-Aufruf, um strukturierte Daten direkt abzurufen.
  • Vorgefertigte Datensätze – Wer bestimmte Datenpunkte benötigt, aber das Scraping ganz vermeiden möchte, dem bietet Bright Data vorgefertigte und bedarfsgerechte Datensätze. Diese Datensätze beinhalten Produktdetails, Preise sowie Bewertungen und sind sofort für E-Commerce-Analysen oder Marktforschungen verwendbar.
  • Web-Unlocker – Der Web-Unlocker bewältigt automatisch Herausforderungen wie CAPTCHAs, Anti-Bot-Mechanismen und komplexe Anfragemuster. In Kombination mit Bibliotheken wie HTTPX oder AIOHTTP können Sie den Scraping-Prozess bei schwer zugänglichen Websites rationalisieren.
  • SERP-API – Falls Sie Daten aus Suchmaschinen extrahieren, vereinfacht die SERP-API von Bright Data diesen Prozess und bietet einen zuverlässigen Echtzeit-Zugang zu Suchergebnissen, Anzeigen und Ranglisten, ohne dass Sie sich Gedanken über die Infrastruktur oder Sperren machen müssen.

Durch die Integration der Bright-Data-Tools mit Python-HTTP-Clients können Sie robuste, leistungsstarke Systeme entwickeln, welche die Datenerfassung vereinfachen und gleichzeitig die üblichen Herausforderungen des Web-Scrapings und der Datenerfassung bewältigen.

Fazit

Requests ist im Reich der HTTP-Clients allein schon wegen seiner Benutzerfreundlichkeit ein Standard. Verglichen mit Requests ist HTTPX eher wie der Umstieg von einer Pferdekutsche auf ein modernes Auto. Es bietet uns ein ausgewogenes Verhältnis zwischen Leistungsstärke und Benutzerfreundlichkeit. AIOHTTP ist wie eine Rakete. Zwar sollte man es nur verwenden, wenn es unbedingt notwendig ist, doch ist es dennoch bei weitem der schnellste HTTP-Client, den es gibt.

Melden Sie sich noch heute bei Bright Data an, um leistungsstarke Datenlösungen zu nutzen und sich den nötigen Wettbewerbsvorsprung für Ihr Unternehmen zu verschaffen. Alle Produkte werden mit einer kostenlosen Testversion geliefert!

Keine Kreditkarte erforderlich