Zurück zum Blog
Anleitungen
Mihnea-Octavian ManolacheLast updated on Mar 31, 202610 min read

Die 3 besten Python-HTTP-Clients für das Web-Scraping

Die 3 besten Python-HTTP-Clients für das Web-Scraping

Wenn es um Web-Scraping geht, macht die Vielzahl der verfügbaren Python-HTTP-Clients Python zu einer der beliebtesten Optionen. Aber was genau sind diese HTTP-Clients und wie kann man sie zum Erstellen eines Web-Scrapers nutzen? Genau dieses Thema werden wir im heutigen Artikel behandeln. Am Ende dieses Artikels sollten Sie ein solides Verständnis für folgende Punkte haben:

  • Was ein HTTP-Client im Allgemeinen ist
  • Was sind die besten Python-HTTP-Clients im Jahr 2022
  • Warum Python eine hervorragende Wahl für das Web-Scraping ist
  • Wie man einen Web-Scraper mithilfe von HTTP-Clients erstellt

Was sind Python-HTTP-Clients und wie verwendet man sie

Um ein tieferes Verständnis dafür zu erlangen, wie das Internet kommuniziert, sollte man sich mit dem Hypertext Transfer Protocol (HTTP) vertraut machen. Unser Hauptaugenmerk liegt heute jedoch auf Python-HTTP-Clients. Ich gehe daher davon aus, dass Sie bereits mit HTTP vertraut sind.

Allgemein gesagt bezeichnet ein HTTP-Client eine Instanz oder ein Programm, das die Kommunikation mit einem Server ermöglicht. Ein Webbrowser kann beispielsweise als HTTP-Client betrachtet werden. Als Programmierer verwenden wir jedoch selten einen tatsächlichen Browser beim Erstellen einer Anwendung, außer wenn wir an einem Web-Scraper arbeiten oder Recherchen durchführen.

Wenn wir also in einem eher programmtechnischen Kontext von HTTP-Clients sprechen, meinen wir damit in der Regel eine Methode oder eine Instanz einer Klasse, die zur Ausführung von HTTP-Anfragen verwendet wird. Da Python zweifellos eine der beliebtesten Programmiersprachen ist (und auch meine persönliche Lieblingssprache), werden wir heute die besten Python-HTTP-Clients besprechen und auch, wie man sie in einem realen Projekt implementiert.

Das HTTP-Protokoll verstehen

Bevor wir fortfahren – auch wenn ich empfehle, die HTTP-Dokumentation zu lesen –, möchte ich kurz auf einige grundlegende HTTP-Konzepte eingehen. Zunächst einmal ist HTTP vielleicht eines der am häufigsten verwendeten Internetprotokolle. Wir nutzen es täglich, um Informationen zwischen Clients und Servern auszutauschen. 

Um dies zu ermöglichen, verwendet HTTP Anfrage-Methoden. Diese Methoden geben die Aktion an, die ein Client auf einem Server ausführen möchte. Wenn Sie beispielsweise Informationen von einem Server abrufen möchten, würden Sie GET verwenden. Wenn Sie etwas an den Server senden möchten, würden Sie POST verwenden. Hier ist eine Liste der gängigsten HTTP-Anfrage-Methoden:

  • GET – Daten vom Server abrufen
  • HEAD – nur den Header abrufen, ohne den Body (die eigentlichen Daten)
  • POST – Informationen an den Server senden
  • PUT – Informationen an den Server senden und alle aktuellen Darstellungen der Ressource ersetzen
  • PATCH – Informationen an den Server senden und die Ressource teilweise ändern
  • DELETE – Die Ressource vom Server löschen

Warum Python für HTTP-Anfragen

Zunächst einmal hat Python eine großartige Syntax und eine noch großartigere Community. Daher eignet es sich perfekt zum Lernen. Ich selbst habe mich, als ich mit dem Programmieren anfing, für Python entschieden. Tatsächlich gehörten Python-HTTP-Clients zu den ersten Technologien, mit denen ich in Berührung kam. Aber das ist ein anderes Thema. 

Mein Ziel für den heutigen Artikel ist es, sicherzustellen, dass Sie nicht nur ein grundlegendes theoretisches Verständnis mitnehmen, sondern auch einen Überblick über die praktische Umsetzung. 

Und Python eignet sich aus einer Reihe von Gründen hervorragend für beides. Um nur einige zu nennen:

  • Syntax – Python zu schreiben ist fast so, als würde man Englisch schreiben. Das Lesen eines Python-Skripts hilft Ihnen also dabei, theoretische Konzepte mit ihrer tatsächlichen Umsetzung in Verbindung zu bringen. 
  • Support – Python hat eine sehr große Community. Meistens reicht eine einfache Frage auf StackOverflow, um die Antwort auf Ihr Problem zu finden, wenn Sie nicht weiterkommen. 
  • Verfügbarkeit – Die Paketbibliothek von Python gehört zu den umfangreichsten. Allein bei den Python-HTTP-Clients gibt es beispielsweise über ein Dutzend Pakete. Wir konzentrieren uns heute jedoch auf die beliebtesten. 

Die 3 (+1) besten Python-HTTP-Clients

Wenn es darum geht, Pakete zu kategorisieren, um die drei besten Python-HTTP-Clients zu ermitteln, ist dies meiner Meinung nach sowohl eine Frage der Funktionalität als auch der persönlichen Vorlieben. Daher ist es richtig zu sagen, dass die folgende Liste meine persönlichen Top 3 der HTTP-Client-Bibliotheken für Python darstellt und keine allgemeine Rangliste ist.

1. Requests – Leistungsstarke Einfachheit

Requests ist wahrscheinlich einer der beliebtesten HTTP-Clients in der Python-Community. Ich mache da keine Ausnahme. Wann immer ich einen neuen Web-Scraper teste, verwende ich Python mit Requests. Es ist so einfach wie „.get“ zu sagen und so leistungsstark wie ein echter Webbrowser. 

Die Requests-Bibliothek bietet unter anderem:

  • SSL-Verifizierung 
  • Proxy-Unterstützung für HTTPS
  • Cookie-Persistenz und Sitzungen
  • Keep-Alive-Funktion
  • Benutzerdefinierte Authentifizierung

Und das sind nur einige davon. Die vollständige Liste der Funktionen findest du hier. Nun zeige ich dir, wie man mit Requests arbeitet:

import requests
r = requests.get("http://google.com")
print(r.test)

Wie du siehst, hilft uns die Requests-Bibliothek mit nur drei Zeilen Code dabei, den HTML-Code von einem Server abzurufen. Im obigen Beispiel senden wir eine GET-Anfrage an den Server und geben das Ergebnis aus. Aber wie gesagt, diese Bibliothek ist viel vielseitiger. Erstellen wir ein komplexeres Beispiel, das Funktionen wie Proxys und POST-Anfragen nutzt:

import requests

def get_params(object):
    params = ''
    for key,value in object.items():
        if list(object).index(key) < len(object) - 1:
            params += f"{key}={value}."
        else:
            params += f"{key}={value}"
    return params

API_KEY = '<YOUR_API_KEY>'

TARGET_URL = 'https://httpbin.org/post'

DATA = {"foo":"bar"}

PARAMETERS = {
    "proxy_type":"datacenter",
    "device":"desktop"
}

PROXY = {
    "http": f"http://webscrapingapi.{ get_params(PARAMETERS) }:{ API_KEY }@proxy.webscrapingapi.com:80",
    "https": f"https://webscrapingapi.{ get_params(PARAMETERS) }:{ API_KEY }@proxy.webscrapingapi.com:8000"
}

response = requests.post(
    url=TARGET_URL,
    data=DATA,
    proxies=PROXY,
    verify=False
)

print(response.text)

Schauen wir uns an, was wir hier tun:

  • Wir definieren die Funktion `get_params`, die ein Objekt entgegennimmt und es als URL-Parameter-String zurückgibt.
  • Wir definieren unsere Variablen: undefinedundefinedundefinedundefinedundefined
  • Wir verwenden die `post`-Methode von Requests, um eine HTTP-POST-Anfrage zu senden.
  • Wir geben den Antworttext aus

2. HTTPX – Requests neu erfunden

HTTPX ist relativ neu auf dem Markt. Dennoch hat es sich in kürzester Zeit zu einem der am häufigsten empfohlenen Python-HTTP-Clients entwickelt. So empfiehlt beispielsweise Flask (eines der größten Web-Frameworks für Python) in seiner offiziellen Dokumentation die Verwendung von HTTPX. 

Als ich sagte, HTTPX sei eine Neuauflage von Requests, dann deshalb, weil sich die beiden Bibliotheken in ihrer Syntax sehr ähneln. Tatsächlich strebt HTTPX vollständige Kompatibilität mit Requests an. Es gibt nur wenige geringfügige Unterschiede im Design zwischen den beiden, die hier hervorgehoben werden. 

So sieht eine einfache POST-Anfrage in HTTPX aus:

import httpx

TARGET_URL = 'https://httpbin.org/post'

DATA = {"foo":"bar"}

r = httpx.post(
   url=TARGET_URL,
   data=DATA,
)

print(r.text)

Wie du sehen kannst, ändern wir im Vergleich zum „Requests“-Beispiel hauptsächlich den Paketnamen. Und da sie sich so ähnlich sind, bleibt die Frage: Warum sollte man HTTPX statt „Requests“ wählen? Nun, zum einen ist HTTPX einer der wenigen Python-HTTP-Clients, der asynchrone Unterstützung bietet. Zusammenfassend lässt sich sagen: HTTPX ist eine hervorragende Wahl, wenn du deinen auf „Requests“ basierenden Code umgestalten möchtest. 

3. urllib3 – Thread-sichere Verbindungen

Python verfügt über mehrere „urllibs“, was neue Programmierer oft verwirrt. Der Hauptunterschied zwischen urllib, urllib2 und urllib3 liegt in den Funktionen der jeweiligen Pakete. urllib war Pythons ursprünglicher HTTP-Client, der in der Standardbibliothek von Python 1.2 enthalten war. urllib2 war die aktualisierte Version, die in Python 1.6 eingeführt wurde und das ursprüngliche urllib ersetzen sollte.

Bei urllib3 handelt es sich jedoch um einen Python-HTTP-Client eines Drittanbieters. Trotz seines Namens steht diese Bibliothek in keinem Zusammenhang mit den beiden „Vorgängern“. Darüber hinaus geht in der Python-Community das Gerücht um, dass keine Absicht besteht, urllib3 in die Standardbibliothek aufzunehmen. Zumindest nicht in naher Zukunft. 

Auch wenn dieses Paket nicht offiziell mit der Python-Standardbibliothek verknüpft ist, nutzen es viele Entwickler, da es Folgendes bietet:

  • Thread-Sicherheit
  • Clientseitige SSL-/TLS-Überprüfung
  • Proxy-Unterstützung für HTTP und SOCKS
  • Vollständige Testabdeckung

Nachdem wir nun den theoretischen Teil behandelt haben, sehen wir uns das Implementierungsbeispiel an:

import urllib3,json

TARGET_URL = 'https://httpbin.org/post'

DATA = {"foo":"bar"}

http = urllib3.PoolManager()

encoded_data = json.dumps(DATA)

r = http.request('POST', TARGET_URL, body=encoded_data)

print(r.data.decode('utf-8'))

Lassen Sie uns die Unterschiede zwischen urllib3 und Requests besprechen:

  • `http` – eine Instanz der `PoolManager`-Methode, die sich um die Details der Thread-Sicherheit und des Connection-Poolings kümmert
  • `encoded_data` – eine konvertierte JSON-Zeichenkette, die die von uns gesendete Nutzlast enthält
  • `r` – die eigentliche POST-Anfrage, die wir mit Hilfe von urllib3 stellen. Hier verwenden wir die `request`-Methode der `PoolManager`-Instanz.

Und schließlich müssen wir die Daten dekodieren, die wir als Antwort auf unsere Anfrage erhalten. Wie Sie sehen können, gibt es einige Dinge, die wir anders handhaben als bei Requests.

Lobende Erwähnung: http.client – Traditioneller Python-HTTP-Client

http.client ist ebenfalls Teil der Standard-Python-Bibliothek. Traditionell wird es von Programmierern nicht direkt verwendet. Urllib nutzt es beispielsweise als Abhängigkeit, um HTTP- und HTTPS-Anfragen zu verarbeiten. Ich habe es in unser Ranking aufgenommen, weil ich denke, dass es für Programmierer gut ist, die „Grundlagen“ der von uns verwendeten Pakete zu kennen.

Auch wenn Sie vielleicht kein tatsächliches Projekt mit http.client erstellen, finden Sie hier ein Implementierungsbeispiel dafür, das Ihnen sicherlich helfen wird, die Funktionsweise von Python-HTTP-Clients besser zu verstehen:

import http.client

TARGET_URL = 'www.httpbin.org'

http = http.client.HTTPSConnection(TARGET_URL)
http.request("GET", "/get")

r = http.getresponse()

print(r.read().decode('utf-8'))

Die `HTTPSConnection`-Instanz benötigt einige Parameter, die du hier nachlesen kannst. In unserem Beispiel definieren wir nur die `method` und die `url` (oder genauer gesagt, den Endpunkt). Außerdem gibt http.client, ähnlich wie urllib3, eine kodierte Antwort zurück. Wir müssen sie also tatsächlich dekodieren, bevor wir sie ausgeben.

Anwendungsfall: Erstellen eines Scrapers mit Requests

Da wir nun wissen, wie man HTTP-Clients verwendet, wollen wir uns ein kleines Projekt vornehmen. Das ist nicht nur hilfreich, um das Gelernte anzuwenden, sondern auch, um dein eigenes Programmierportfolio aufzuwerten. 

Da Python-HTTP-Clients häufig zum Sammeln von Informationen von Servern verwendet werden, besteht die gängigste Anwendung dieser Technologien darin, einen Web-Scraper zu erstellen. Im weiteren Verlauf werden wir uns daher darauf konzentrieren, wie man einen Web-Scraper mit HTTP-Clients in Python erstellt. Da ich einen persönlichen Favoriten habe – Requests – werde ich diesen für dieses Projekt verwenden. Du kannst ihn jedoch als Ausgangspunkt nutzen und sogar anpassen, um einige der anderen Technologien zu verwenden, die wir besprochen haben. Lass uns ohne weitere Umschweife mit dem Programmieren beginnen:

1. Projekteinrichtung

Beginnen wir damit, ein neues Verzeichnis anzulegen, in dem wir die Dateien für unseren Web-Scraper ablegen werden. Öffne nun ein neues Terminalfenster und wechsle mit `cd` in dieses Verzeichnis. Hier wollen wir eine neue virtuelle Umgebung einrichten. Wenn du ein UNIX-ähnliches Betriebssystem verwendest, kannst du folgenden Befehl nutzen:

~ » python3 -m venv env && source env/bin/activate              

Erstellen Sie nun einfach eine neue Python-Datei, die unsere Logik enthalten wird, und öffnen Sie sie in Ihrer bevorzugten IDE. Wenn Sie das Terminal verwenden möchten, fügen Sie einfach den folgenden Befehl ein:

~ » touch scraper.py && code .                                         

2. Installation der Abhängigkeiten

Wir werden pip verwenden, um die für dieses Projekt benötigten Pakete zu installieren. Bisher haben wir festgelegt, dass wir Requests verwenden werden, aber das reicht für einen Web-Scraper nicht aus. Ein Web-Scraper beinhaltet auch die Verarbeitung der Daten. Das bedeutet, dass wir den von den Servern gesammelten HTML-Code parsen müssen. Glücklicherweise bietet die Python-Bibliothek eine große Auswahl an Paketen. Für dieses Projekt werden wir jedoch BeautifulSoup verwenden. Um die Pakete zu installieren, fügen Sie einfach den folgenden Befehl ein:

~ » python3 -m pip install requests bs4                                    

3. Die Logik schreiben

Wir werden unseren Code in zwei Abschnitte unterteilen: einen für die Datenextraktion und einen für die Datenbearbeitung. Der erste Teil wird vom Requests-Paket abgedeckt, während der zweite Teil von BeautifulSoup abgedeckt wird. Lassen Sie uns ohne weitere Umschweife mit dem Programmieren beginnen, beginnend mit dem Extraktionsteil:

import requests

def scrape( url = None ):
   # if there is no URL, there is no need to use Python HTTP clients
   # We will print a message and stop execution
   if url == None:
       print('[!] Please add a target!')
       return

   response = requests.get( url ) 
   return response

In diesem Abschnitt definieren wir eine Funktion mit nur einem Parameter: der Ziel-URL. Wenn die URL nicht angegeben wird, geben wir eine Meldung aus und brechen die Ausführung ab. Andernfalls verwenden wir die get-Methode von Requests, um die Antwort zurückzugeben. Nun wissen wir, dass Python-HTTP-Clients weitere Methoden abdecken, also fügen wir einen bedingten Parameter hinzu:

import requests

def scrape( method = 'get', url = None, data = None ):
   # if there is no URL, there is no need to use Python HTTP clients
   # We will print a message and stop execution
   if url == None:
       print('[!] Please add a target!')
       return

   if method.lower() == 'get':
       response = requests.get( url )

   elif method.lower() == 'post':
       if data == None:
           print('[!] Please add a payload to your POST request!')
           return
       response = requests.post( url, data )
      
   return response

Wie du sehen kannst, haben wir unserer Funktion einige weitere Parameter hinzugefügt. Der Parameter `method` gibt an, welche Methode für unsere Anfrage verwendet werden soll. Der Parameter `data` steht für die Nutzdaten, die wir mit der POST-Anfrage senden. Standardmäßig ist die Methode GET, daher ist der Parameter `method` nicht erforderlich. 

Herausforderung: Füge dieser Funktion weitere Methoden hinzu und erweitere die Fähigkeiten unseres Scrapers. Das macht nicht nur Spaß, sondern ist auch ein guter Lernansatz. Außerdem kannst du den Code so anpassen, dass er zu deinem eigenen wird, und ihn deinem Portfolio hinzufügen.

Bisher haben wir uns mit der Datenextraktion befasst. Lassen Sie uns nun den HTML-Code analysieren und etwas damit anfangen:

from bs4 import BeautifulSoup

def extract_elements(data = None, el = None):
   if data == None:
       print('[!] Please add some data!')
       return

   if el == None:
       print('[!] Please specify which elements you are targeting!')
       return

   soup = BeautifulSoup(data.text, 'html.parser')
   elements = soup.find_all(el)

   return elements

Ein Web-Scraper sollte jedoch in der Lage sein, spezifischere Daten zu extrahieren. Er sollte beispielsweise Elemente anhand ihres CSS-Selektors finden und zurückgeben können. Fügen wir also die Logik hinzu, die diesen Teil übernimmt:

from bs4 import BeautifulSoup

def extract_elements(data = None, el = None, attr = None, attr_value = None):
   if data == None:
       print('[!] Please add some data!')
       return

   if el == None:
       print('[!] Please specify which elements you are targeting!')
       return

   soup = BeautifulSoup(data.text, 'html.parser')
   elements = soup.find_all(el, { attr : attr_value })

   return elements

Mit BeautifulSoup können wir bestimmte Daten anhand ihrer Attribute extrahieren. Deshalb haben wir hier zwei neue Parameter hinzugefügt, die uns helfen, Elemente anhand ihrer Attribute zu finden und zu extrahieren.

Wir haben nun alles, was wir brauchen. Jetzt müssen wir nur noch die beiden Abschnitte kombinieren, und schon haben wir unseren Web-Scraper. Sobald du deinen Code zusammengestellt hast, gehe einfach wie folgt vor:

  • Erstellen Sie eine neue Variable, die die mit Requests extrahierten Daten enthält 
  • Geben Sie die von BeautifulSoup zurückgegebenen Elemente aus

Hier sind die beiden fehlenden Teile deines Codes:

data = scrape('GET', 'https://webscrapingapi.com')
print( extract_elements(data, 'ul') )

Ich bin mir sicher, dass du bereits herausgefunden hast, was alles bewirkt, und eine Übersetzung an dieser Stelle nicht mehr nötig ist. Genau wie bei unserem Scraper fordere ich dich auf, mit der Funktion `extract_elements` zu experimentieren und sie dazu zu bringen, mehr zu tun, als nur Elemente zurückzugeben. 

Fazit

Wenn man ein neues Programmierkonzept lernt, ist es meiner Meinung nach am besten, mit den verschiedenen verfügbaren Technologien zu experimentieren. Wenn es jedoch darum geht, die Infrastruktur für ein größeres Projekt aufzubauen, ist es besser, sich über die Stärken und Schwächen der einzelnen Technologien zu informieren, bevor man sich für eine entscheidet. 

Ich hoffe, dieser Artikel hat dir in jedem Fall geholfen und du hast nun ein solides Verständnis davon, wie die Python-HTTP-Clients funktionieren. Ich ermutige dich auch, ein wenig herumzuprobieren, da ich sicher bin, dass du so das richtige Paket für dich finden wirst.

Über den Autor
Mihnea-Octavian Manolache, Full-Stack-Entwickler @ WebScrapingAPI
Mihnea-Octavian ManolacheFull-Stack-Entwickler

Mihnea-Octavian Manolache ist Full-Stack- und DevOps-Entwickler bei WebScrapingAPI. Er entwickelt Produktfunktionen und sorgt für die Wartung der Infrastruktur, die den reibungslosen Betrieb der Plattform gewährleistet.

Los geht’s

Sind Sie bereit, Ihre Datenerfassung zu erweitern?

Schließen Sie sich den über 2.000 Unternehmen an, die WebScrapingAPI nutzen, um Webdaten im Unternehmensmaßstab ohne zusätzlichen Infrastrukturaufwand zu extrahieren.