Wiederholungen von Anfragen in Python

Bemerkungen: 0

Web Scraping ist eine effektive Methode, um Daten aus dem Internet zu extrahieren. Viele Entwickler bevorzugen die Python-Anforderungsbibliothek zur Durchführung von Web-Scraping-Projekten, da sie einfach und effektiv ist. Doch so großartig sie auch ist, die Request-Bibliothek hat ihre Grenzen. Ein typisches Problem, das beim Web Scraping auftritt, sind fehlgeschlagene Anfragen, die oft zu einer instabilen Datenextraktion führen. In diesem Artikel werden wir den Prozess der Implementierung von Anfragewiederholungen in Python durchgehen, damit Sie HTTP-Fehler behandeln können und Ihre Web-Scraping-Skripte stabil und zuverlässig bleiben.

Einstieg in die Anforderungsbibliothek

Lassen Sie uns zuerst unsere Umgebung einrichten. Stellen Sie sicher, dass Sie Python und eine IDE Ihrer Wahl installiert haben. Installieren Sie dann die requests-Bibliothek, falls Sie sie noch nicht haben.

pip install requests

Nach der Installation können wir mit dem Python-Modul requests eine Anfrage an example.com senden. Hier ist eine einfache Funktion, die genau das tut:

import requests

def send_request(url):
    """
    Sendet eine HTTP-GET-Anfrage an die angegebene URL und gibt den Antwortstatuscode aus.
    
    Parameters:
        url (str): Die URL, an die die Anfrage gesendet werden soll.
    """
    response = requests.get(url)
    print('Response Status Code: ', response.status_code)

send_request('https://example.com')

Die Code-Ausgabe ist unten dargestellt:

How to implement request retries in Python.png

Schauen wir uns die HTTP-Statuscodes genauer an, um sie besser zu verstehen.

Verstehen der HTTP-Statuscodes

Der Server antwortet auf eine HTTP-Anfrage mit einem Statuscode, der das Ergebnis der Anfrage angibt. Hier ist eine kurze Zusammenfassung:

  1. 1xx (informativ): Die Anfrage wurde empfangen und wird weiter bearbeitet.
  2. 2xx (Erfolg): Die Anfrage wurde empfangen, verstanden und akzeptiert.
    • 200 OK: Die Anfrage war erfolgreich. Dies ist das grüne Licht der HTTP-Statuscodes.
  3. 3xx (Umleitung): Es sind weitere Maßnahmen erforderlich, um die Anfrage abzuschließen.
  4. 4xx (Client-Fehler): Bei der Anfrage ist ein Fehler aufgetreten, oft aufgrund eines Fehlers auf der Client-Seite.
  5. 5xx (Serverfehler): Der Server konnte eine gültige Anfrage aufgrund eines Fehlers auf seiner Seite nicht erfüllen.
    • 500 Interner Serverfehler: Der Server war nicht in der Lage, die Anfrage zu bearbeiten. Dies zeigt an, dass der Server auf eine unerwartete Bedingung gestoßen ist, die ihn daran hinderte, die Anfrage zu erfüllen. Dies ist das Äquivalent des HTTP-Statuscodes zur roten Ampel.
    • 504 Gateway-Zeitüberschreitung: Der Server hat nicht rechtzeitig eine Antwort vom Upstream-Server erhalten. Dies ist das HTTP-Statuscode-Äquivalent der Wartezimmer-Timeout-Ampel.

In unserem Beispiel bedeutet der Statuscode 200, dass die Anfrage an https://example.com abgeschlossen wurde. Das ist die Art des Servers zu sagen: "Hier ist alles in Ordnung, Ihre Anfrage war erfolgreich".

Diese Statuscodes können auch bei der Erkennung von Bots eine Rolle spielen und anzeigen, wenn der Zugriff aufgrund von botähnlichem Verhalten eingeschränkt ist.

Im Folgenden finden Sie eine kurze Auflistung von HTTP-Fehlercodes, die hauptsächlich aufgrund von Bot-Erkennung und Authentifizierungsproblemen auftreten.

  1. 429 zu viele Anfragen: Dieser Statuscode zeigt an, dass der Nutzer zu viele Anfragen in einer bestimmten Zeit gesendet hat ("Ratenbegrenzung"). Dies ist eine übliche Antwort, wenn Bots vordefinierte Anfragegrenzen überschreiten.
  2. 403 forbidden: Dieser Code wird zurückgegeben, wenn der Server sich weigert, die Anfrage zu erfüllen. Dies kann vorkommen, wenn der Server aufgrund des User-Agents oder anderer Kriterien vermutet, dass die Anfrage von einem Bot stammt.
  3. 401 unauthorized: Dieser Status kann verwendet werden, wenn der Zugriff eine Authentifizierung erfordert, über die der Bot nicht verfügt.
  4. 503 service unavailable (Dienst nicht verfügbar): wird manchmal verwendet, um anzuzeigen, dass der Server vorübergehend nicht in der Lage ist, die Anfrage zu bearbeiten, was bei automatischen Verkehrsspitzen vorkommen kann.

Implementierung des Retry-Mechanismus in Python

Lassen Sie uns nun einen einfachen Wiederholungsmechanismus in Python schreiben, um HTTP GET-Anfragen mit der requests-Bibliothek zu stellen. Es gibt Zeiten, in denen Netzwerkanfragen aufgrund von Netzwerkproblemen oder Serverüberlastung fehlschlagen. Wenn also unsere Anfrage fehlschlägt, sollten wir diese Anfragen erneut versuchen.

Basischer Wiederholungsmechanismus

Die Funktion send_request_with_basic_retry_mechanism stellt HTTP-GET-Anfragen an eine bestimmte URL mit einem grundlegenden Wiederholungsmechanismus, der nur wiederholt wird, wenn eine Netzwerk- oder Anfrageausnahme wie ein Verbindungsfehler auftritt. Er würde die Anfrage maximal max_retry mal wiederholen. Wenn alle Versuche mit einer solchen Ausnahme fehlschlagen, wird die zuletzt aufgetretene Ausnahme ausgelöst.

import requests
import time

def send_request_with_basic_retry_mechanism(url, max_retries=2):
    """
    Sendet eine HTTP-GET-Anfrage an eine URL mit einem einfachen Wiederholungsmechanismus.
    
    Parameters:
        url (str): Die URL, an die die Anfrage gesendet werden soll.
        max_retries (int): Die maximale Anzahl der Wiederholungsversuche für die Anfrage.

    Raises:
        requests.RequestException: Löst die letzte Ausnahme aus, wenn alle Wiederholungsversuche fehlschlagen.

    """
    for attempt in range(max_retries):
        try:
            response = requests.get(url)
            print('Response status: ', response.status_code)
            break  # Schleife verlassen, wenn Anfrage erfolgreich
        except requests.RequestException as error:
            print(f"Attempt {attempt+1} failed:", error)
            if attempt < max_retries - 1:
                print(f"Retrying...")
                time.sleep(delay)  # Warten Sie, bevor Sie es erneut versuchen.
            else:
                print("Max retries exceeded.")
                # Wiederholung der letzten Ausnahme, wenn die maximale Anzahl der Wiederholungsversuche erreicht ist
                raise
                send_request_with_basic_retry_mechanism('https://example.com')

Vorgezogener Wiederholungsmechanismus

Passen wir nun den grundlegenden Wiederholungsmechanismus an, um Szenarien zu behandeln, in denen die Website, die wir scrapen wollen, Bot-Erkennungsmechanismen einsetzt, die zu einer Blockierung führen können. Um solche Szenarien zu bewältigen, müssen wir die Anfrage mehrfach wiederholen, da es sich nicht nur um Bot-Erkennungsblockaden handeln kann, sondern auch um Netzwerk- oder Serverprobleme.

Die folgende Funktion send_request_with_advance_retry_mechanism sendet eine HTTP-GET-Anfrage an die angegebene URL mit optionalen Wiederholungsversuchen und Wiederholungsverzögerung. Sie versucht, die Anfrage mehrmals für die angegebene Anzahl von Versuchen zu senden und gibt den Antwortstatuscode aus, wenn die Anfrage erfolgreich beantwortet wird. Tritt während der Anfrage ein Fehler auf, wird die Fehlermeldung ausgegeben und die Anfrage erneut versucht. Zwischen den einzelnen Versuchen wird die angegebene Verzögerung für die Wiederholung abgewartet. Schlägt die Anfrage auch nach der angegebenen Anzahl von Wiederholungsversuchen fehl, wird die zuletzt aufgetretene Ausnahme ausgelöst.

Der Verzögerungsparameter ist wichtig, da er verhindert, dass der Server mit mehreren Anfragen in kurzen Abständen bombardiert wird. Stattdessen wird gewartet, bis der Server genügend Zeit hat, die Anfrage zu bearbeiten, so dass der Server denkt, dass ein Mensch und kein Bot die Anfragen stellt. Der Wiederholungsmechanismus sollte also verzögert werden, um eine Überlastung des Servers oder eine langsame Antwort des Servers zu vermeiden, die Anti-Bot-Mechanismen auslösen könnten.

import requests
import time

def send_request_with_advance_retry_mechanism(url, max_retries=3, delay=1):
    """
    Sendet eine HTTP-GET-Anfrage an die angegebene URL mit einem erweiterten Wiederholungsmechanismus.
    
    Parameters:
        url (str): Die URL, an die die Anfrage gesendet werden soll.
        max_retries (int): Die maximale Anzahl der Wiederholungsversuche für die Anfrage. Standard ist 3.
        delay (int): Die Verzögerung (in Sekunden) zwischen den Wiederholungsversuchen. Standard ist 1.

    Raises:
        requests.RequestException: Löst die letzte Ausnahme aus, wenn alle Wiederholungsversuche fehlschlagen.
    """
    for attempt in range(max_retries):
        try:
            response = requests.get(url)
            # Bei den Statuscodes 4xx oder 5xx wird eine Ausnahme ausgelöst
            response.raise_for_status()
            print('Response Status Code:', response.status_code)
        except requests.RequestException as e:
           # Fehlermeldung und Versuchsnummer ausgeben, wenn die Anfrage fehlschlägt
            print(f"Attempt {attempt+1} failed:", e)
            if attempt < max_retries - 1:
                # Druckt die Nachricht über den erneuten Versuch und wartet, bevor es erneut versucht wird
                print(f"Retrying in {delay} seconds...")
                time.sleep(delay)
            else:
                # Wenn die maximale Anzahl der Wiederholungsversuche überschritten wird, wird eine Meldung gedruckt und die Ausnahme erneut ausgelöst
                print("Max retries exceeded.")
                raise

# Beispiel für die Verwendung
send_request_with_advance_retry_mechanism('https://httpbin.org/status/404')

Hier sind die Nachteile dieser Umsetzung:

  • Alle Statuscodes, die zu den Bereichen 4xx und 5xx gehören, werden erneut versucht. Anfragen, die zu einem 404 (Not Found) Statuscode führen, müssen jedoch nicht erneut versucht werden.
  • Einige Bot-Erkennungsdienste können mit einem Statuscode von 200 (OK) antworten, aber der Inhalt der Antwort kann abweichen. Diese Situation wird in der aktuellen Implementierung nicht behandelt. Die Implementierung einer Inhaltslängenüberprüfung könnte dieses Problem beheben.

Hier ist der korrigierte Code zusammen mit Kommentaren, die sich mit den Nachteilen befassen:

import requests
import time

def send_request_with_advance_retry_mechanism(url, max_retries=3, delay=1, min_content_length=10):
    """
    Sendet eine HTTP-GET-Anfrage an die angegebene URL mit einem erweiterten Wiederholungsmechanismus.

    Parameters:
        url (str): Die URL, an die die Anfrage gesendet werden soll.
        max_retries (int): Die maximale Anzahl der Wiederholungsversuche für die Anfrage. Der Standardwert ist 3.
        delay (int): Die Verzögerung (in Sekunden) zwischen den Wiederholungsversuchen. Standard ist 1.
        min_content_length (int): Die Mindestlänge des Antwortinhalts, die als gültig angesehen wird. Der Standardwert ist 10.

    Raises:
        requests.RequestException: Löst die letzte Ausnahme aus, wenn alle Wiederholungsversuche fehlschlagen.
    """
    for attempt in range(max_retries):
        try:
            response = requests.get(url)
            # Bei den Statuscodes 4xx oder 5xx wird eine Ausnahme ausgelöst.
            response.raise_for_status()
            
            # Prüfen Sie, ob der Statuscode der Antwort 404 ist
            if response.status_code == 404:
                print("404 Error: Not Found")
                break  # Schleife für 404-Fehler beenden
            
            # Prüfen, ob die Länge des Antworttextes kleiner ist als die angegebene Mindestlänge des Inhalts
            if len(response.text) < min_content_length:
                print("Response text length is less than specified minimum. Retrying...")
                time.sleep(delay)
                continue  # Wiederholen Sie die Anfrage.
            
            print('Response Status Code:', response.status_code)
            # Wenn die Bedingungen erfüllt sind, aus der Schleife aussteigen.
            break
            
        except requests.RequestException as e:
            print(f"Attempt {attempt+1} failed:", e)
            if attempt < max_retries - 1:
                print(f"Retrying in {delay} seconds...")
                time.sleep(delay)
            else:
                print("Max retries exceeded.")
                # Wiederholung der letzten Ausnahme, wenn die maximale Anzahl der Wiederholungsversuche erreicht ist
                raise

# Beispiel für die Verwendung
send_request_with_advance_retry_mechanism('https://httpbin.org/status/404')

Behandlung bestimmter HTTP-Fehler mit Proxys

Bei bestimmten Fehlern wie 429 Too Many Requests kann die Verwendung rotierender Proxys helfen, die Anfragen zu verteilen und eine Ratenbegrenzung zu vermeiden.

Der folgende Code implementiert eine erweiterte Wiederholungsstrategie zusammen mit der Verwendung von Proxys. Auf diese Weise können wir einen Mechanismus zur Wiederholung von Python-Anfragen implementieren. Die Verwendung von qualitativ hochwertigen Web-Scraping-Proxys ist ebenfalls wichtig. Diese Proxys sollten einen guten Algorithmus für die Proxy-Rotation und einen zuverlässigen Pool haben.

import requests
import time

def send_request_with_advance_retry_mechanism(url, max_retries=3, delay=1, min_content_length=10):
    """
    Sendet eine HTTP-GET-Anfrage an die angegebene URL mit einem erweiterten Wiederholungsmechanismus.

    Parameters:
        url (str): Die URL, an die die Anfrage gesendet werden soll.
        max_retries (int): Die maximale Anzahl der Wiederholungsversuche für die Anfrage. Standard ist 3.
        delay (int): Die Verzögerung (in Sekunden) zwischen den Wiederholungsversuchen. Der Standardwert ist 1.
   
    Raises:
        requests.RequestException: Löst die letzte Ausnahme aus, wenn alle Wiederholungsversuche fehlschlagen.
    """
    
    proxies = {
        "http": "http://USER:PASS@HOST:PORT",
        "https": "https://USER:PASS@HOST:PORT"
    }
    
    for attempt in range(max_retries):
        try:
            response = requests.get(url, proxies=proxies, verify=False)
            # Bei den Statuscodes 4xx oder 5xx wird eine Ausnahme ausgelöst.
            response.raise_for_status()
            
            # Prüfen Sie, ob der Antwort-Statuscode 404 ist.
            if response.status_code == 404:
                print("404 Error: Not Found")
                break  # Exit loop for 404 errors
            
            # Prüfen, ob die Länge des Antworttextes weniger als 10 Zeichen beträgt
            if len(response.text) < min_content_length:
                print("Response text length is less than 10 characters. Retrying...")
                time.sleep(delay)
                continue  # Wiederholen Sie die Anfrage.
            
            print('Response Status Code:', response.status_code)
            # Wenn die Bedingungen erfüllt sind, aus der Schleife aussteigen.
            break
            
        except requests.RequestException as e:
            print(f"Attempt {attempt+1} failed:", e)
            if attempt < max_retries - 1:
                print(f"Retrying in {delay} seconds...")
                time.sleep(delay)
            else:
                print("Max retries exceeded.")
                # Wiederholung der letzten Ausnahme, wenn die maximale Anzahl der Wiederholungsversuche erreicht ist
                raise

send_request_with_advance_retry_mechanism('https://httpbin.org/status/404')

Wiederholungen von Anfragen in Python sind für effektives Web-Scraping unerlässlich. Die von uns besprochenen Methoden zur Verwaltung von Wiederholungen können helfen, Blockierungen zu verhindern und die Effizienz und Zuverlässigkeit der Datenerfassung zu verbessern. Durch die Implementierung dieser Techniken werden Ihre Web-Scraping-Skripte robuster und weniger anfällig für die Erkennung durch Bot-Schutzsysteme.

Bemerkungen:

0 Bemerkungen