Gibt es eine einfache Möglichkeit, eine URL in Python anzufordern und NICHT Weiterleitungen zu folgen?

92

Wenn man sich die Quelle von urllib2 ansieht, scheint es am einfachsten zu sein, HTTPRedirectHandler in eine Unterklasse zu unterteilen und dann build_opener zu verwenden, um den Standard-HTTPRedirectHandler zu überschreiben. Dies scheint jedoch eine Menge (relativ komplizierter) Arbeit zu sein, um das zu tun, was es sein sollte ziemlich einfach.

John
quelle
2
Für Googler: Die Verwendung der Anforderungsbibliothek erspart Ihnen viel Kopfzerbrechen: docs.python-requests.org und siehe Marians Antwort unten, es ist sehr elegant.
Alojz Janez
Ich bin damit einverstanden, dass Anfragen heutzutage der richtige Weg sind. Ich habe diesen Kommentar und Marians Antwort positiv bewertet, aber ich lasse die Antwort als vergeben, da sie zu der Zeit die beste war.
John
1
@ John Awards sind gut, aber die Zeit vergeht und dies ist eine von der Community bearbeitete Seite. Der Fokus liegt auf guten Antworten und nicht auf den Menschen. Er wird seine Upvote-Punkte behalten. Sie führen Tonnen anderer Programmierer in veraltete Bibliotheken.
Mit
1
OK Fair genug. Ich habe die Antwort auf die Anfrage akzeptiert.
John

Antworten:

177

Hier ist der Weg der Anfragen :

import requests
r = requests.get('http://github.com', allow_redirects=False)
print(r.status_code, r.headers['Location'])
Marian
quelle
5
Dann schauen Sie, um r.headers['Location']zu sehen, wohin es Sie geschickt hätte
patricksurry
Beachten Sie, dass es scheint , dass Anfragen normalisieren Locationzu location.
Hamish
2
Mit @Hamish requestskönnen Sie auf Header sowohl in kanonischer Form als auch in Kleinbuchstaben zugreifen. Siehe docs.python-requests.org/en/master/user/quickstart/…
Marian
1
Ab 2019 in Python 3 scheint dies für mich nicht mehr zu funktionieren. (Ich bekomme einen Schlüsselfehler.)
Max von Hippel
35

Dive Into Python hat ein gutes Kapitel zum Umgang mit Weiterleitungen mit urllib2. Eine andere Lösung ist httplib .

>>> import httplib
>>> conn = httplib.HTTPConnection("www.bogosoft.com")
>>> conn.request("GET", "")
>>> r1 = conn.getresponse()
>>> print r1.status, r1.reason
301 Moved Permanently
>>> print r1.getheader('Location')
http://www.bogosoft.com/new/location
olt
quelle
7
Alle, die von Google hierher kommen, beachten Sie bitte, dass der aktuelle Weg der folgende ist: stackoverflow.com/a/14678220/362951 Die Anforderungsbibliothek erspart Ihnen viel Kopfzerbrechen.
Mit
Der Link zu "Dive Into Python" ist tot.
Guettli
11

Dies ist ein urllib2-Handler, der Weiterleitungen nicht folgt:

class NoRedirectHandler(urllib2.HTTPRedirectHandler):
    def http_error_302(self, req, fp, code, msg, headers):
        infourl = urllib.addinfourl(fp, headers, req.get_full_url())
        infourl.status = code
        infourl.code = code
        return infourl
    http_error_300 = http_error_302
    http_error_301 = http_error_302
    http_error_303 = http_error_302
    http_error_307 = http_error_302

opener = urllib2.build_opener(NoRedirectHandler())
urllib2.install_opener(opener)
Carles Barrobés
quelle
Ich teste eine API und beschäftige mich mit einer Anmeldemethode, die auf eine Seite umleitet, die mir egal ist, aber nicht das gewünschte Sitzungscookie mit der Antwort auf die Weiterleitung sendet. Genau das brauchte ich dafür.
Tim Wilder
9

Das redirectionsSchlüsselwort in der httplib2Anforderungsmethode ist ein roter Hering. Anstatt die erste Anforderung zurückzugeben, wird eine RedirectLimitAusnahme ausgelöst, wenn ein Umleitungsstatuscode empfangen wird. Um wieder die inital Antwort , die Sie festlegen müssen , follow_redirectsum Falseauf das HttpObjekt:

import httplib2
h = httplib2.Http()
h.follow_redirects = False
(response, body) = h.request("http://example.com")
Ian Mackinnon
quelle
8

Ich nehme an, das würde helfen

from httplib2 import Http
def get_html(uri,num_redirections=0): # put it as 0 for not to follow redirects
conn = Http()
return conn.request(uri,redirections=num_redirections)
Ashish
quelle
5

Ich bin der zweite Zeiger von olt, um in Python einzutauchen . Hier ist eine Implementierung mit urllib2-Redirect-Handlern, mehr Arbeit als es sein sollte? Vielleicht Achselzucken.

import sys
import urllib2

class RedirectHandler(urllib2.HTTPRedirectHandler):
    def http_error_301(self, req, fp, code, msg, headers):  
        result = urllib2.HTTPRedirectHandler.http_error_301( 
            self, req, fp, code, msg, headers)              
        result.status = code                                 
        raise Exception("Permanent Redirect: %s" % 301)

    def http_error_302(self, req, fp, code, msg, headers):
        result = urllib2.HTTPRedirectHandler.http_error_302(
            self, req, fp, code, msg, headers)              
        result.status = code                                
        raise Exception("Temporary Redirect: %s" % 302)

def main(script_name, url):
   opener = urllib2.build_opener(RedirectHandler)
   urllib2.install_opener(opener)
   print urllib2.urlopen(url).read()

if __name__ == "__main__":
    main(*sys.argv) 
Aaron Maenpaa
quelle
3
Sieht falsch aus ... Dieser Code folgt tatsächlich den Weiterleitungen (indem er den ursprünglichen Handler aufruft und somit eine HTTP-Anfrage
ausgibt
5

Der kürzeste Weg ist jedoch

class NoRedirect(urllib2.HTTPRedirectHandler):
    def redirect_request(self, req, fp, code, msg, hdrs, newurl):
        pass

noredir_opener = urllib2.build_opener(NoRedirect())
Tzury Bar Yochay
quelle
1
Wie ist das der kürzeste Weg? Es enthält nicht einmal den Import oder die eigentliche Anfrage.
Marian
Ich wollte diese Lösung bereits veröffentlichen und war ziemlich überrascht, diese Antwort unten zu finden. Es ist sehr prägnant und sollte meiner Meinung nach die beste Antwort sein.
Benutzer
Darüber hinaus erhalten Sie mehr Freiheit. Auf diese Weise können Sie steuern, welchen URLs Sie folgen möchten .
Benutzer
Ich bestätige, das ist der einfachste Weg. Eine kurze Bemerkung für diejenigen, die debuggen möchten. Vergessen Sie nicht, dass Sie beim Öffnen des Öffners mehrere Handler einstellen können, z. B.: opener = urllib.request.build_opener(debugHandler, NoRedirect())Wo debugHandler=urllib.request.HTTPHandler()und debugHandler.set_http_debuglevel (1). Am Ende:urllib.request.install_opener(opener)
StashOfCode