Biblioteka żądań Pythona przekierowuje nowy adres URL

102

Przeglądałem dokumentację Python Requests, ale nie widzę żadnej funkcjonalności dla tego, co próbuję osiągnąć.

W moim skrypcie ustawiam allow_redirects=True.

Chciałbym wiedzieć, czy strona została przekierowana na coś innego, jaki jest nowy adres URL.

Na przykład, jeśli początkowy adres URL to: www.google.com/redirect

A końcowy URL to www.google.co.uk/redirected

Jak uzyskać ten adres URL?

Daniel Pilch
źródło
Sprawdź tę odpowiedź, aby poradzić sobie z urllib2
horkruksa

Odpowiedzi:

165

Szukasz historii żądań .

response.historyAtrybut jest lista odpowiedzi, które doprowadziły do ostatecznej zawartości, którą można znaleźć w response.url.

response = requests.get(someurl)
if response.history:
    print("Request was redirected")
    for resp in response.history:
        print(resp.status_code, resp.url)
    print("Final destination:")
    print(response.status_code, response.url)
else:
    print("Request was not redirected")

Próbny:

>>> import requests
>>> response = requests.get('http://httpbin.org/redirect/3')
>>> response.history
(<Response [302]>, <Response [302]>, <Response [302]>)
>>> for resp in response.history:
...     print(resp.status_code, resp.url)
... 
302 http://httpbin.org/redirect/3
302 http://httpbin.org/redirect/2
302 http://httpbin.org/redirect/1
>>> print(response.status_code, response.url)
200 http://httpbin.org/get
Martijn Pieters
źródło
httpbin.org podaje 404 z jakiegoś powodu, ale httpbingo.org (ten sam schemat adresu URL) działał dobrze dla mnie.
Preston Badeer
@PrestonBadeer: To znany problem: github.com/postmanlabs/httpbin/issues/617 . Na szczęście nie jest istotne, że wersja demonstracyjna działa w odpowiedzi.
Martijn Pieters
69

To odpowiedź na nieco inne pytanie, ale skoro sam utknąłem w tym, mam nadzieję, że może to być przydatne dla kogoś innego.

Jeśli chcesz użyć allow_redirects=Falsei dostać się bezpośrednio do pierwszego obiektu przekierowania, zamiast podążać za ich łańcuchem, i po prostu chcesz uzyskać lokalizację przekierowania bezpośrednio z obiektu odpowiedzi 302, to r.urlnie zadziała. Zamiast tego jest to nagłówek „Lokalizacja”:

r = requests.get('http://github.com/', allow_redirects=False)
r.status_code  # 302
r.url  # http://github.com, not https.
r.headers['Location']  # https://github.com/ -- the redirect destination
hwjp
źródło
Dziękuję - to przyspieszyło mój skrypt odsyłający do adresu URL (który miał tysiące adresów URL) o kilka sekund.
ahinkle
Czy wiesz, o co chodzi r.next? Myślałem, że będzie to PreparedRequestwskazanie na adres URL przekierowania, ale wydaje się, że tak nie jest ...
Elias Strehle
33

Myślę, że request.head zamiast request.get będzie bezpieczniejsze do wywołania podczas obsługi przekierowania adresu URL, sprawdź tutaj problem z github :

r = requests.head(url, allow_redirects=True)
print(r.url)
Geng Jiawen
źródło
1
To powinna być akceptowana odpowiedź. Krótkie i słodkie.
Volatil3
5
@ Volatil3: Nie wszystkie serwery odpowiadają na żądanie HEAD w taki sam sposób, jak w przypadku GET.
Blender
10

W przypadku pythona 3.5 możesz użyć następującego kodu:

import urllib.request
res = urllib.request.urlopen(starturl)
finalurl = res.geturl()
print(finalurl)
Shuai.Z
źródło
to jest poprawna odpowiedź dla Pythona 3.5, zajęło mi trochę czasu znalezienie, dzięki
jjj