Urllib2.HTTPError oder urllib.error.HTTPError überschreiben und trotzdem Antwort-HTML lesen

72

Ich erhalte die Antwort "HTTP-Fehler 500: Interner Serverfehler", möchte jedoch weiterhin die Daten im Fehler-HTML lesen.

Mit Python 2.6 rufe ich normalerweise eine Seite ab mit:

import urllib2
url = "http://google.com"
data = urllib2.urlopen(url)
data = data.read()

Beim Versuch, dies für die fehlerhafte URL zu verwenden, wird die Ausnahme angezeigt urllib2.HTTPError:

urllib2.HTTPError: HTTP Error 500: Internal Server Error

Wie kann ich solche Fehlerseiten (mit oder ohne urllib2) abrufen, während sie interne Serverfehler zurückgeben?

Beachten Sie, dass bei Python 3 die entsprechende Ausnahme lautet urllib.error.HTTPError.

backus
quelle

Antworten:

136

Das HTTPError ist ein dateiähnliches Objekt . Sie können es fangen und dann readseinen Inhalt.

try:
    resp = urllib2.urlopen(url)
    contents = resp.read()
except urllib2.HTTPError, error:
    contents = error.read()
Joe Holloway
quelle
2
Sobald wir error.read () ausgeführt haben, gibt error.read () anschließend eine leere Zeichenfolge zurück. Manchmal bringt dies den Code an anderer Stelle durcheinander. Wie können wir den Inhalt des Fehlers höflich für andere zurückstellen?
Colonel Panic
1
@Matt Ich habe das noch nie versucht, aber da es sich um ein dateiähnliches Objekt handelt, können Sie möglicherweise error.seek(0)den "Dateizeiger" auf den Anfang des Streams zurücksetzen. Nicht jedes dateiähnliche Objekt ist erforderlich, um den Direktzugriffsteil der E / A-Schnittstelle zu implementieren. Daher ist nicht sicher, ob es funktioniert. Wenn dies nicht der Fall ist, können Sie dies in einer eigenen Frage stellen, um ein größeres Publikum anzusprechen.
Joe Holloway
1
Beachten Sie, dass sich HTTPError in entarteten Fällen möglicherweise nicht als dateiähnliches Objekt verhält. Stellen Sie sicher, dass read () mit hasattr verfügbar ist.
Ron
2
Da der zugrunde liegende Stream eine http-Antwort ist, ist er nicht durchsuchbar, was bedeutet, dass Sie ihn nicht aufrufen seek()können.
Remcoder
9

Wenn Sie meinen, Sie möchten den Körper des 500 lesen:

request = urllib2.Request(url, data, headers)
try:
        resp = urllib2.urlopen(request)
        print resp.read()
except urllib2.HTTPError, error:
        print "ERROR: ", error.read()

In Ihrem Fall müssen Sie die Anforderung nicht erstellen. Mach einfach

try:
        resp = urllib2.urlopen(url)
        print resp.read()
except urllib2.HTTPError, error:
        print "ERROR: ", error.read()

Sie überschreiben also nicht urllib2.HTTPError, sondern behandeln nur die Ausnahme.

sberry
quelle
1
Nein, ich möchte den HTML-Code lesen, den der Server an den Browser des Benutzers senden würde, wenn er versehentlich eine der 500 internen Fehlerseiten aufgerufen hätte. Genau wie wenn urllib auf einer 404-Seite kaputt gegangen ist (ich bin mir nicht sicher, ob dies der Fall ist, habe ich es nicht versucht), möchte ich das HTML lesen, das die 404-Seite bereitstellt (z. B. wenn die Site eine benutzerdefinierte 404-Seite erstellt).
Backus
-1
alist=['http://someurl.com']

def testUrl():
    errList=[]
    for URL in alist:
        try:
            urllib2.urlopen(URL)
        except urllib2.URLError, err:
            (err.reason != 200)
            errList.append(URL+" "+str(err.reason))
            return URL+" "+str(err.reason)
    return "".join(errList)

testUrl()
Gal Levy
quelle
1
Sie sollten Ihrer Antwort einen beschreibenden Text hinzufügen
Hussein Khalil
err.reasonbietet nicht die gleichen Informationen, die err.read()bietet. Letzteres kann insbesondere nützlich sein.
Acumenus