2008-09-21 8 views
43

Patrząc na źródło urllib2 wygląda na to, że najprościej to zrobić, to podklasować HTTPRedirectHandler, a następnie użyć build_opener, aby zastąpić domyślny HTTPRedirectHandler, ale wydaje się, że jest to dużo (stosunkowo skomplikowana) praca, aby zrobić to, co wydaje się być powinno być całkiem proste.Czy istnieje prosty sposób, aby zażądać adresu URL w python i NIE wykonywać przekierowań?

+2

Dla Googlersami: przy użyciu biblioteki wnioski pozwoli Ci zaoszczędzić sporo bólu głowy : http://docs.python-requests.org/ i zobacz poniżej odpowiedź Mariana, jest bardzo elegancka. –

+0

Zgadzam się, że prośby to sposób na dzisiejsze dni. Przegapiłem ten komentarz i odpowiedź Mariana, ale pozostawiam odpowiedź jako przyznaną, ponieważ była najlepsza w tym czasie. – John

+1

@John nagrody są dobre, ale czas się toczy i jest to strona edytowana przez społeczność. Nacisk kładzie się na dobre odpowiedzi, a nie na ludzi. Będzie utrzymywał swoje punkty upatrywania. Wprowadzasz w błąd ton innych programistów w przestarzałych bibliotekach. – mit

Odpowiedz

83

Oto Requests sposób:

import requests 
r = requests.get('http://github.com', allow_redirects=False) 
print(r.status_code, r.headers['Location']) 
+3

Następnie spójrz na 'r.headers ['Location']', aby zobaczyć, gdzie wysłałbyś ciebie. – patricksurry

+0

Zauważ, że wygląda na to, że Żąda normalizują 'Location' na' location'. – Hamish

+0

@Hamish 'requests' umożliwia dostęp do nagłówków zarówno w formie kanonicznej, jak i małymi literami. Zobacz http://docs.python-requests.org/en/master/user/quickstart/#response-headers – Marian

34

Dive Into Python ma dobry rozdział dotyczący obsługi przekierowań za pomocą urllib2. Inne rozwiązanie to 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 
+2

Każdy, kto przyjeżdża tutaj z google, należy pamiętać, że aktualny sposób postępowania jest następujący: http://stackoverflow.com/a/14678220/362951 Biblioteka żądań pozwoli Ci zaoszczędzić wiele bólu głowy. – mit

5

I sekunda wskaźnik olt na Dive into Python. Oto implementacja za pomocą mechanizmów obsługi przekierowań urllib2, więcej pracy niż powinno być? Może, wzruszam ramionami.

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) 
+3

Wygląda niepoprawnie ... Ten kod faktycznie działa po przekierowaniach (przez wywołanie oryginalnej procedury obsługi, a tym samym wysłanie żądania HTTP), a następnie podniesienie wyjątku –

8

przypuszczam pomogłoby

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) 
11

To obsługi urllib2 że nie pójdą przekierowania:

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) 
+0

Jestem jednostką testującą interfejs API i obsługującą metodę logowania, która przekierowuje do strona Nie obchodzi mnie, ale nie wysyła pożądanego pliku cookie sesji z odpowiedzią na przekierowanie. Właśnie tego potrzebowałem. –

4

Najkrótsza droga jest jednak

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

noredir_opener = urllib2.build_opener(NoRedirect()) 
+1

Jak to jest najkrótsza droga? Nie zawiera nawet importu ani faktycznego żądania. – Marian

+0

Już zamierzałem opublikować to rozwiązanie i byłem zaskoczony, że znalazłem tę odpowiedź na dole. Jest bardzo zwięzła i moim zdaniem powinna być najlepszą odpowiedzią. – user

+0

Co więcej, daje więcej swobody, w ten sposób można [kontrolować, jakie adresy URL śledzić] (http://stackoverflow.com/a/28057731/3075942). – user

7

redirections słowem kluczowym w metodzie żądania jest czerwony śledź. Zamiast zwracania pierwszego żądania spowoduje podniesienie wyjątku RedirectLimit, jeśli otrzyma kod statusu przekierowania. Aby przywrócić inital odpowiedź trzeba ustawić follow_redirects do False na obiekcie Http:

import httplib2 
h = httplib2.Http() 
h.follow_redirects = False 
(response, body) = h.request("http://example.com") 
+0

Dlaczego jest tak mało głosów? TO to, co zadziałało dla mnie. – brisssou

Powiązane problemy