Zum Inhalt

So führen Sie Web Scrape mit HTTPX und Python durch

Unter Web Scraping versteht man das automatische Extrahieren von Daten von Websites. Dabei handelt es sich um eine gängige Technik zum Sammeln großer Datenmengen für Analysen, maschinelles Lernen und mehr. In Python gibt es viele tolle Bibliotheken, die das Web-Scraping einfach machen. Eine beliebte Option ist HTTPX.

HTTPX ist ein leistungsstarker und moderner HTTP-Client für Python. Es wurde von den Entwicklern hinter Requests erstellt und ist stark von Requests inspiriert, fügt aber auch neue Funktionen wie HTTP/2-Unterstützung hinzu.

In diesem umfassenden Leitfaden erfahren Sie, wie Sie mithilfe von HTTPX effektiv Websites in Python crawlen.

Erste Schritte mit HTTPX

Um zu beginnen, kann HTTPX über pip installiert werden:

pip install httpx

Alternativ kann Poesie verwendet werden:

poetry add httpx

Nach der Installation kann HTTPX importiert und verwendet werden:

import httpx

response = httpx.get(‘https://example.com‘)
print(response.text)

Dadurch wird eine GET-Anfrage an example.com gestellt und der HTML-Code der Homepage gedruckt.

HTTPX verfügt über eine einfache API und unterstützt alle gängigen HTTP-Verben wie GET, POST, PUT, DELETE, HEAD, OPTIONS usw.

Einige der wichtigsten Merkmale sind:

  • HTTP/1.1- und HTTP/2-Unterstützung
  • Asynchrone API im aiohttp-Stil
  • Verbindungspooling und Keepalive
  • Proxy-Unterstützung
  • Timeout-Konfiguration
  • Cookie-Persistenz
  • Vertraute API im Anfragestil

Schauen wir uns als Nächstes einige gängige Nutzungsmuster an.

Anfragen mit HTTPX stellen

Um eine GET-Anfrage zu stellen, muss die httpx.get() Methode kann verwendet werden:

response = httpx.get(‘https://example.com‘)

Ebenso httpx.post(), httpx.put(), httpx.delete()usw. können für andere HTTP-Verben verwendet werden.

Parameter wie Header, Cookies, Timeout usw. können als Schlüsselwortargumente übergeben werden:

response = httpx.get(
  ‘https://httpbin.org/headers‘,
  headers = {
    ‘User-Agent‘: ‘MyBot 1.0‘
  },
  timeout = 10.0
)

Die Antwort enthält Eigenschaften wie status_code, headers, text, json(), Etc.:

print(response.status_code)
print(response.headers)
print(response.text)
json = response.json()

Sie können die Antwort auch inkrementell streamen, indem Sie das Antwortobjekt durchlaufen.

Verwendung eines HTTPX-Clients

Für die meisten Scraping-Aufgaben wird die Verwendung eines Persistenten empfohlen httpx.Client Beispiel.

Der Client verwaltet Dinge wie Verbindungspooling, Sitzungen, Cookies usw. über mehrere Anfragen hinweg.

import httpx

client = httpx.Client()

response = client.get(‘https://example.com‘)
print(response.text)

response = client.get(‘https://httpbin.org/cookies/set?name=foo‘)
print(response.text) 

response = client.get(‘https://httpbin.org/cookies‘)
print(response.json())

Hier stellen wir mehrere Anfragen mit demselben Client, der die Cookie-Persistenz automatisch verwaltet.

Sie können beim Erstellen des Clients auch Optionen wie Header, Proxys, Authentifizierung usw. konfigurieren:

client = httpx.Client(
  headers = {
    ‘User-Agent‘: ‘MyBot 1.0‘,
    ‘Authorization‘: ‘Bearer xxx‘   
  },
  proxies = ‘http://192.168.1.1:8181/‘,
  auth = (‘username‘, ‘password‘)
)

Schauen wir uns nun die asynchronen Erstellungsanfragen an.

Asynchrone Anfragen mit HTTPX

Um Anfragen in Python asynchron zu stellen, bietet HTTPX eine AsyncClient:

import httpx

async with httpx.AsyncClient() as client:
  response = await client.get(‘https://example.com‘) 

Wir verwenden async with um den Client zu initialisieren, await auf Anfrage und schließt den Client anschließend automatisch.

Um mehrere URLs gleichzeitig zu scannen, können wir verwenden asyncio.gather():

import httpx
import asyncio

async def get_url(url):
  async with httpx.AsyncClient() as client:
    response = await client.get(url)
    return response.text

urls = [‘https://example.com‘, ‘https://httpbin.org‘, ‘https://python.org‘]

async def main():
  responses = await asyncio.gather(*[get_url(url) for url in urls])
  print(responses)

asyncio.run(main())

asyncio.gather() Wartet gleichzeitig auf mehrere Coroutinen und gibt Ergebnisse in der Reihenfolge der erwarteten Ergebnisse zurück.

Es gibt auch andere Optionen wie asyncio.as_completed() um sie nach Abschluss zu verarbeiten:

tasks = [get_url(url) for url in urls]

async def main():
  for result in asyncio.as_completed(tasks):
    print(await result)

Async IO ermöglicht das gleichzeitige Abrufen mehrerer Seiten gleichzeitig, was zur Beschleunigung des Scrapings hilfreich ist.

Schauen wir uns als Nächstes das Scraping von Daten aus HTML- und JSON-Antworten an.

Scraping von HTML- und JSON-Antworten

Für das HTML-Scraping können wir einen Parser wie Beautiful Soup verwenden, um Daten zu extrahieren:

from bs4 import BeautifulSoup

response = httpx.get(‘https://en.wikipedia.org/wiki/Python_(programming_language)‘)

soup = BeautifulSoup(response.text, ‘html.parser‘)

for link in soup.select(‘.toctext‘):
  print(link.text.strip())

Dadurch wird der Inhalt des Inhaltsverzeichnisses der Wikipedia-Seite gedruckt.

Für JSON-Antworten bietet HTTPX eine integrierte Funktion .json() Verfahren:

response = httpx.get(‘https://api.github.com/repos/encode/httpx‘)

json = response.json()
print(json[‘description‘])

Das json= Der Parameter kann auch zum Serialisieren von JSON-Daten in Anfragen verwendet werden.

Zusammen mit einem Parser können wir Scraper erstellen, um Daten aus APIs und Websites zu extrahieren.

Umgang mit Problemen und Fehlern

Beim Scraping treten häufig Probleme wie Verbindungsfehler, Zeitüberschreitungen, Geschwindigkeitsbegrenzungen usw. auf.

HTTPX bietet Ausnahmen und Tools, um diese angemessen zu behandeln.

Timeouts

Um mit langsamen Antworten umzugehen, können Sie einen benutzerdefinierten Wert angeben timeout Parameter. Der Standardwert beträgt 5 Sekunden.

response = httpx.get(‘https://example.com‘, timeout=10.0) 

Bei Überschreitung a httpx.TimeoutException tritt ein:

try:
  response = httpx.get(‘https://example.com‘, timeout=0.001)
except httpx.TimeoutException:
  print(‘Request timed out‘)

Für bestimmte Websites oder Seiten können längere Zeitüberschreitungen erforderlich sein.

HTTP-Fehler

Für HTTP-Fehler wie 400, 500 usw. gilt die response.raise_for_status() Methode kann verwendet werden:

try:
  response = httpx.get(‘https://httpbin.org/status/500‘)
  response.raise_for_status()
except httpx.HTTPStatusError:
  print(‘HTTP Error occurred‘)  

Dadurch wird bei jedem 4xx- oder 5xx-Statuscode eine Ausnahme ausgelöst.

Anfragen erneut versuchen

Um Wiederholungslogik hinzuzufügen, können externe Pakete wie tenacity kann verwendet werden:

from tenacity import retry, stop_after_attempt

@retry(stop=stop_after_attempt(3))
def make_request():
  response = httpx.get(‘https://example.com‘)
  response.raise_for_status()
  return response.json()

data = make_request()

Hier versuchen wir es bei jeder Ausnahme bis zu dreimal. Es kann auch eine erweiterte Wiederholungslogik definiert werden.

Grenzwerte für parallele Anfragen

Wenn Sie viele Anfragen parallel stellen, kann es zu Verbindungsbeschränkungen kommen.

Das limits Mit dem Parameter können Optionen wie die maximale Anzahl an Verbindungen konfiguriert werden:

client = httpx.AsyncClient(
  limits = httpx.Limits(max_connections=20)
)

Durch die Optimierung dieses Parameters basierend auf der Zielsite können Einschränkungen vermieden werden.

Durch die Behebung dieser häufigen Probleme können widerstandsfähigere Schaber gebaut werden.

Best Practices für das Scraping

Hier sind einige Tipps zum Erstellen effektiver Web-Scraper mit HTTPX:

  • Verwenden Sie einen HTTPX-Client – Clients bieten Verbindungspooling, Cookie-Persistenz und andere Vorteile.

  • Höflich kratzen – Begrenzen Sie die Anfrageraten, um eine Überlastung der Server zu vermeiden. Verwenden Sie zufällige Verzögerungen und Drosselung.

  • Behandeln Sie Fehler – Verwenden Sie Try/Except-Blöcke, Statusprüfungen und Wiederholungsversuche, um Probleme zu lösen.

  • Verwenden Sie Async IO – Scrapen Sie Seiten gleichzeitig, um die Geschwindigkeit zu verbessern. Beschränken Sie jedoch die Parallelität, um Verbote zu vermeiden.

  • Benutzeragenten randomisieren – Drehen Sie zufällige Benutzeragentenzeichenfolgen, um menschlicher zu wirken.

  • Verwenden Sie Proxys – Rotieren Sie verschiedene Proxys/IPs, um Anfragen zu verteilen.

  • Daten zwischenspeichern und speichern – Speichern Sie gescrapte Daten in Dateien/Datenbanken, um ein erneutes Scrapen zu vermeiden.

Durch die Befolgung von Best Practices wie diesen können robustere und wartungsfreundlichere Schaber gebaut werden.

Fortgeschrittene Schabetechniken

Schauen wir uns einige erweiterte Scraping-Funktionen von HTTPX an.

Scraping-Authentifizierungsseiten

Zum Scrapen authentifizierter Seiten unterstützt HTTPX mehrere Authentifizierungstypen wie Basic-, Digest- und Bearer-Authentifizierung:

client = httpx.Client(
  auth = (‘username‘, ‘password‘)
)

response = client.get(‘https://api.example.com/users/me‘)

Authentifizierungsdaten werden bei allen Anfragen automatisch beibehalten.

Umgang mit Cookies

Das cookies Parameter kann zum Senden benutzerdefinierter Cookies verwendet werden:

client = httpx.Client(
  cookies = {
    ‘sessionId‘: ‘xxxx‘
  }
)

response = client.get(‘https://example.com/dashboard‘) 

Und vom Server gesetzte Cookies bleiben automatisch im Client bestehen.

Streaming-Antworten

Bei großen Antworten können Sie diese inkrementell streamen, indem Sie das Antwortobjekt iterieren:

response = client.get(‘https://example.com/bigfile‘)
for chunk in response:
  process(chunk) 

Dadurch wird vermieden, dass die gesamte Antwort in den Speicher geladen werden muss.

Proxy-Unterstützung

Um Anfragen über einen Proxyserver weiterzuleiten, muss der proxies Parameter kann verwendet werden:

proxy = ‘http://192.168.0.1:8888‘ 

client = httpx.Client(proxies = {‘http‘: proxy, ‘https‘: proxy})

Durch die Rotation verschiedener Proxys können Anfragen von verschiedenen IPs verteilt werden.

Benutzerdefinierte Header

Sie können Anforderungsheader wie Benutzeragenten fälschen oder randomisieren:

client = httpx.Client(headers = {
  ‘User-Agent‘: ‘MyBot 1.0‘ 
})

Dies ahmt die Header eines echten Browsers nach.

Durch diese erweiterten Funktionen können robuste Scraper mit HTTPX und Python erstellt werden.

Beispiel-Schaber

Schauen wir uns nun einige Beispiele für Scraper an, die mit HTTPX erstellt wurden.

Reddit API Scraper

Hier ist ein einfacher Scraper für die Reddit-API:

import httpx

client = httpx.Client()

subreddit = ‘python‘ 
listing = ‘hot‘
limit = 10

response = client.get(f‘https://www.reddit.com/r/{subreddit}/{listing}.json?limit={limit}‘)

data = response.json()[‘data‘]

for post in data[‘children‘]:
   title = post[‘data‘][‘title‘]
   score = post[‘data‘][‘score‘]
   print(f"{title} (Score: {score})")

Dadurch werden Daten zu den Top-Beiträgen aus dem Python-Subreddit abgerufen. Die API gibt JSON zurück, das wir analysieren können.

Wir könnten diesen Scraper erweitern, um Daten aus mehreren Subreddits zu extrahieren, Ergebnisse in einer Datenbank zu speichern usw.

News-Artikel-Schaber

Hier ist ein einfacher News-Scraper, der Artikel von einer Website extrahiert:

from bs4 import BeautifulSoup
import httpx

client = httpx.Client()

response = client.get("https://example.com/news")
soup = BeautifulSoup(response.text, ‘html.parser‘)

for article in soup.select(‘.article‘):

  title = article.select_one(‘.article-title‘).text
  content = article.select_one(‘.article-content‘).text

  print(title) 
  print(content)
  print() 

Das findet alles .article Elemente, extrahiert die Titel- und Inhaltsfelder und druckt die Artikel.

Auch dies könnte erweitert werden, um zusätzliche Felder zu extrahieren, Daten zu analysieren, in einer Datenbank zu speichern usw.

Suchergebnisse Schaber

Und hier ist ein Beispiel-Scraper für Google-Suchergebnisse:

import httpx

query = "httpx python"
url = f"https://www.google.com/search?q={query}"

client = httpx.Client()
response = client.get(url)

from bs4 import BeautifulSoup
soup = BeautifulSoup(response.text, ‘html.parser‘)

for result in soup.select(‘.tF2Cxc‘):

  title = result.select_one(‘.DKV0Md‘).text
  link = result.select_one(‘.yuRUbf a‘)[‘href‘]

  print(title)
  print(link) 
  print()

Dadurch wird Google nach einer bestimmten Suchanfrage durchsucht, die Ergebnislinks/Titel analysiert und ausgedruckt.

Auch hier könnten viele Verbesserungen vorgenommen werden, z. B. das Extrahieren von Suchergebnissen, zusätzliche Felder, das Scrapen von Ergebnisseiten, das Erkennen von Captchas usw.

Diese Beispiele veranschaulichen gängige Scraping-Muster mit HTTPX. Dieselben Techniken können zum Erstellen von Scrapern für viele Websites und APIs angewendet werden.

Zusammenfassung

Zusammenfassend bietet HTTPX einen leistungsstarken HTTP-Client zum Erstellen von Python-Web-Scrapern. Hier sind einige wichtige Punkte:

  • HTTPX verfügt über eine einfache API im Anfragestil zum Senden von Anfragen.

  • Durch die Async-Unterstützung können gleichzeitig Anfragen gestellt werden.

  • Robuste Fehlerbehandlung mit Zeitüberschreitungen, Wiederholungsversuchen und Statusprüfungen.

  • Scrapen Sie HTML-Seiten ganz einfach mit Beautiful Soup und JSON-APIs.

  • Persistente Clients bieten Verbindungspooling, Sitzungen und Cookie-Verarbeitung.

  • Fortschrittliche Techniken wie Proxys, Header und Authentifizierung ermöglichen anspruchsvolle Scraper.

  • Befolgen Sie Best Practices wie die Verwendung von Drosselung, zufälligen Verzögerungen und Benutzeragenten.

HTTPX erleichtert den Einstieg in das Scraping mit Python. Mit robuster Fehlerbehandlung und asynchroner Parallelität können skalierbare Scraper entwickelt werden.

Probieren Sie HTTPX bei Ihrem nächsten Python-Web-Scraping-Projekt aus!

Stichworte:

Mitreden

E-Mail-Adresse wird nicht veröffentlicht. Pflichtfelder sind MIT * gekennzeichnet. *