Wenn Sie mit HTTP arbeiten, sind fehlgeschlagene Anfragen eine unvermeidliche Realität, mit der man umgehen muss. In der Webentwicklung zeigt ein Status 200 eine erfolgreiche Antwort an. Wir erhalten jedoch nicht immer eine 200, und dieser Leitfaden hilft Ihnen zu verstehen, wie Sie mit diesen Nicht-200-Statuscodes umgehen können.
Laut Mozilla lassen sich Statuscodes in folgende Kategorien unterteilen:
- 100-199: Informationsantworten
- 200-299: Erfolgreiche Antworten
- 300-399: Weiterleitungsnachrichten
- 400-499: Client-Fehlermeldungen
- 500-599: Server-Fehlermeldungen
Was sind Statuscodes?
Fehlercodes sind wichtig. Beim Erstellen von clientseitigen Programmen wie Web-Scrapern müssen wir uns hauptsächlich auf Statuscodes im Bereich 400+ und 500+ konzentrieren. Codes im 400er-Bereich decken im Allgemeinen Fehler auf der Client-Seite ab, wie Authentifizierungsprobleme, Rate-Limiting, Timeouts und den berüchtigten 404: Datei nicht gefunden-Fehler. Im 500er-Bereich haben wir es in der Regel mit Serverproblemen zu tun.
Mozilla dokumentiert seit Jahrzehnten Webentwicklungsstandards des W3C und der IETF. Nachfolgend finden Sie eine Liste häufiger Fehlercodes, denen Sie begegnen könnten. Diese Liste ist nicht vollständig. Diese Fehler stammen aus Mozillas offizieller Dokumentation. Je nach Zielseite können Ihre Codes leicht abweichen, aber die Logik sollte dieselbe bleiben.
| Statuscode | Bedeutung | Beschreibung |
|---|---|---|
| 400 | Bad Request | Überprüfen Sie Ihr Anforderungsformat |
| 401 | Unauthorized | Überprüfen Sie Ihren API-Schlüssel |
| 403 | Forbidden | Sie können nicht auf diese Daten zugreifen |
| 404 | Not Found | Seite/Endpunkt existiert nicht |
| 408 | Request Timeout | Anfrage abgelaufen, erneut versuchen |
| 429 | Too Many Requests | Verlangsamen Sie Ihre Anfragen |
| 500 | Internal Server Error | Allgemeiner Serverfehler, Anfrage wiederholen |
| 501 | Not Implemented | Server unterstützt dies noch nicht |
| 502 | Bad Gateway | Fehlgeschlagene Antwort von einem vorgelagerten Server |
| 503 | Service Unavailable | Server vorübergehend nicht verfügbar, später erneut versuchen |
| 504 | Gateway Timeout | Timeout beim Warten auf einen vorgelagerten Server |
Wiederholungsstrategien
Bei der Implementierung eines Wiederholungsmechanismus können Sie vorgefertigte Bibliotheken wie HTTPAdapter und Tenacity verwenden. Je nach Anwendungsfall möchten Sie möglicherweise auch Ihre eigene Wiederholungslogik schreiben.
Typischerweise benötigen wir ein Wiederholungslimit und eine Backoff-Strategie. Wir brauchen ein Limit, damit wir nicht in einer unendlichen Wiederholungsschleife gefangen werden. Wir müssen schrittweise zurückgehen, um den Host-Server zu respektieren. Wenn Ihre Anfragen zu schnell kommen, werden Sie blockiert oder der Server wird überlastet.
- Wiederholungslimits: Sie müssen ein Limit setzen. Nach X Wiederholungsversuchen gibt Ihr Scraper auf.
- Backoff-Algorithmus: Dieser ist relativ einfach. Sie möchten mit einem kleinen Backoff beginnen und ihn bei jeder Wiederholung erhöhen. Wir beginnen mit 0,3, erhöhen dann auf 0,6 und 1,2 und so weiter.
Wir möchten unsere Anfragen bis zu einem bestimmten Limit wiederholen. Nach jeder fehlgeschlagenen Anfrage möchten wir etwas länger warten.
HTTPAdapter
Mit HTTPAdapter müssen wir drei Dinge konfigurieren: total, backoff_factor und status_forcelist. allowed_methods ist keine wirkliche Anforderung, macht unseren Code jedoch sicherer, indem es hilft, unsere Wiederholungsbedingungen zu definieren. Im folgenden Code verwenden wir httpbin, um automatisch einen Fehler zu erzwingen und unsere Wiederholungslogik auszulösen.
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
#create a session
session = requests.Session()
#configure retry settings
retry = Retry(
total=3, #maximum retries
backoff_factor=0.3, #time between retries (exponential backoff)
status_forcelist=(429, 500, 502, 503, 504), #status codes to trigger a retry
allowed_methods={"GET", "POST"}
)
#mount the adapter with our custom settings
adapter = HTTPAdapter(max_retries=retry)
session.mount("http://", adapter)
session.mount("https://", adapter)
#actually make a request with our retry logic
try:
print("Making a request with retry logic...")
response = session.get("https://httpbin.org/status/500")
response.raise_for_status()
print("✅ Request successful:", response.status_code)
except requests.exceptions.RequestException as e:
print("❌ Request failed after retries:", e)
Sobald wir ein Session-Objekt erstellt haben, gehen wir wie folgt vor:
- Erstellen Sie ein
Retry-Objekt und definieren Sie Folgendes:total: Das maximale Limit für die Wiederholung einer Anfrage.backoff_factor: Wartezeit zwischen Wiederholungen. Diese passt sich exponentiell an, wenn unsere Wiederholungen zunehmen.status_forcelist: Eine Liste fehlerhafter Statuscodes. Alle Codes in dieser Liste lösen automatisch eine Wiederholung aus.
- Erstellen Sie ein
HTTPAdapter-Objekt mit unsererretry-Variable:adapter = HTTPAdapter(max_retries=retry). - Sobald wir den
adaptererstellt haben, binden wir ihn mitsession.mount()an die HTTP- und HTTPS-Methoden.
Wenn Sie diesen Code ausführen, werden unsere drei Wiederholungen (total=3) ausgeführt und Sie erhalten die folgende Ausgabe.
Making a request with retry logic...
❌ Request failed after retries: HTTPSConnectionPool(host='httpbin.org', port=443): Max retries exceeded with url: /status/500 (Caused by ResponseError('too many 500 error responses'))
Tenacity
Sie können auch Tenacity verwenden, eine beliebte Open-Source-Wiederholungsbibliothek für Python. Sie ist nicht auf HTTP beschränkt, bietet uns aber eine ausdrucksstarke, verständliche Möglichkeit, Wiederholungen zu implementieren.
Zunächst müssen Sie es installieren.
pip install tenacity
Nach der Installation erstellen wir einen Decorator und verwenden ihn, um eine Requests-Funktion zu umhüllen. Mit unserem @retry-Decorator fügen wir die Argumente stop, wait und retry hinzu.
import requests
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type, RetryError
#define a retry strategy
@retry(
stop=stop_after_attempt(3), #retry up to 3 times
wait=wait_exponential(multiplier=0.3), #exponential backoff
retry=retry_if_exception_type(requests.exceptions.RequestException), #retry on request failures
)
def make_request():
print("Making a request with retry logic...")
response = requests.get("https://httpbin.org/status/500")
response.raise_for_status()
print("✅ Request successful:", response.status_code)
return response
# Attempt to make the request
try:
make_request()
except RetryError as e:
print("❌ Request failed after all retries:", e)
Die Logik und Einstellungen hier sind unserem ersten Beispiel mit HTTPAdapter sehr ähnlich.
stop=stop_after_attempt(3): Dies weisttenacityan, nach 3 fehlgeschlagenen Wiederholungen aufzugeben.wait=wait_exponential(multiplier=0.3)verwendet dasselbe Warten wie zuvor. Es erhöht sich ebenfalls exponentiell, genau wie vorher.retry=retry_if_exception_type(requests.exceptions.RequestException)weisttenacityan, diese Logik bei jederRequestExceptionanzuwenden.make_request()sendet eine Anfrage an unseren Fehler-Endpunkt. Es erhält alle Eigenschaften des Decorators, den wir darüber erstellt haben.
Wenn Sie diesen Code ausführen, erhalten Sie eine ähnliche Ausgabe.
Making a request with retry logic...
Making a request with retry logic...
Making a request with retry logic...
❌ Request failed after all retries: RetryError[<Future at 0x75e762970760 state=finished raised HTTPError>]
Eigenen Wiederholungsmechanismus erstellen
Sie können auch Ihren eigenen Wiederholungsmechanismus erstellen. Bei benutzerdefiniertem Code kann dies oft der beste Ansatz sein. Mit relativ wenig Code können wir denselben Effekt erzielen, den wir von diesen Bibliotheken erhalten.
Im folgenden Code müssen wir sleep für unser exponentielles Backoff importieren. Wir legen erneut unsere Konfiguration fest: total, backoff_factor und bad_codes. Wir verwenden dann eine while-Schleife, um unsere Wiederholungslogik zu halten. while wir noch Versuche haben und noch nicht erfolgreich waren, versuchen wir die Anfrage.
import requests
from time import sleep
#create a session
session = requests.Session()
#define our retry settings
total = 3
backoff_factor = 0.3
bad_codes = [429, 500, 502, 503, 504]
#try counter and success boolean
current_tries = 0
success = False
#attempt until we succeed or run out of tries
while current_tries < total and not success:
try:
print("Making a request with retry logic...")
response = session.get("https://httpbin.org/status/500")
if response.status_code in bad_codes:
raise requests.exceptions.HTTPError(f"Received {response.status_code}, triggering retry")
print("✅ Request successful:", response.status_code)
success = True
except requests.exceptions.RequestException as e:
print(f"❌ Request failed: {e}, retries left: {total-current_tries}")
sleep(backoff_factor)
backoff_factor = backoff_factor * 2
current_tries+=1
Die eigentliche Logik wird hier durch eine einfache while-Schleife gesteuert.
- Wenn
response.status_codein unserer Liste derbad_codesenthalten ist, lösen wir eine Ausnahme aus. - Wenn eine Anfrage fehlschlägt:
- Geben wir eine Fehlermeldung in der Konsole aus.
sleep(backoff_factor)wartet vor dem Senden der nächsten Anfrage.backoff_factor = backoff_factor * 2verdoppelt unserenbackoff_factorfür den nächsten Versuch.- Wir erhöhen
current_tries, damit wir nicht unbegrenzt in der Schleife bleiben.
Hier ist die Ausgabe unserer benutzerdefinierten Wiederholungslogik.
Making a request with retry logic...
❌ Request failed: Received 500, triggering retry, retries left: 3
Making a request with retry logic...
❌ Request failed: Received 500, triggering retry, retries left: 2
Making a request with retry logic...
❌ Request failed: Received 500, triggering retry, retries left: 1
Blockierungen umgehen
In der Praxis werden einige Seiten Sie blockieren. Es ist Best Practice, immer einen Proxy mit Python-Requests zu verwenden. Mit einem Proxy wird Ihre Anfrage über eine andere Maschine geleitet. Dies schützt Ihre Identität und verhindert, dass Ihre IP-Adresse von Ihrer Zielseite blockiert wird. Wir haben sogar einen detaillierten Leitfaden zum Umgehen von IP-Sperren. Unsere Residential-Proxys sind darauf ausgelegt, diese Herausforderungen zu meistern.
Fazit
Jetzt wissen Sie, wie Sie fehlgeschlagene HTTP-Anfragen in Python behandeln. Ob Sie einen Scraper, einen API-Client oder Automatisierungstools schreiben, Sie wissen, wie Sie mit diesen Problemen umgehen. Um alle Arten von fehlgeschlagenen Anfragen zu vermeiden, haben wir Produkte wie die Web Unlocker API und den Scraping-Browser entwickelt. Diese Tools verarbeiten automatisch Anti-Bot-Maßnahmen, CAPTCHA-Herausforderungen und IP-Sperren und gewährleisten nahtloses und effizientes Web-Scraping selbst für die anspruchsvollsten Websites.
Registrieren Sie sich jetzt und starten Sie noch heute Ihren kostenlosen Test.