Python 请求库重定向新的 URL

我一直在查看 Python 请求文档,但是我看不到任何与我试图实现的目标相关的功能。

在我的脚本中,我正在设置 allow_redirects=True

我想知道如果页面已被重定向到其他东西,什么是新的网址。

例如,如果起始 URL 是: www.google.com/redirect

最终的 URL 是 www.google.co.uk/redirected

我怎样才能得到那个网址?

269603 次浏览

文档上有这个简介 https://requests.readthedocs.io/en/master/user/quickstart/#redirection-and-history

import requests


r = requests.get('http://www.github.com')
r.url
#returns https://www.github.com instead of the http page you asked for

你要找的是 请求历史

response.history属性是导致最终 URL 的响应列表,可以在 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")

演示:

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

我认为在处理 URL 重定向时,使用 requests.head而不是 requests.get会更安全。检查 GitHub 问题 给你:

r = requests.head(url, allow_redirects=True)
print(r.url)

这是在回答一个稍微不同的问题,但是因为我自己被这个问题困住了,我希望它可能对其他人有用。

如果您想使用 allow_redirects=False并直接获得第一个重定向对象,而不是遵循它们的链条,并且您只想直接从302响应对象中获得重定向位置,那么 r.url将无法工作。取而代之的是“ Location”标题:

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

对于 python3.5,可以使用以下代码:

import urllib.request
res = urllib.request.urlopen(starturl)
finalurl = res.geturl()
print(finalurl)

我无法使用请求库,只能另辟蹊径。下面是我发布的代码,作为这篇文章的解决方案。(获取带有请求的重定向 URL)

通过这种方式,您实际打开浏览器,等待浏览器将 URL 记录到历史日志中,然后读取历史记录中的最后一个 URL。我为 google chrom 写了这段代码,但是如果你使用不同的浏览器,你应该可以跟随。

import webbrowser
import sqlite3
import pandas as pd
import shutil


webbrowser.open("https://twitter.com/i/user/2274951674")
#source file is where the history of your webbroser is saved, I was using chrome, but it should be the same process if you are using different browser
source_file = 'C:\\Users\\{your_user_id}\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\History'
# could not directly connect to history file as it was locked and had to make a copy of it in different location
destination_file = 'C:\\Users\\{user}\\Downloads\\History'
time.sleep(30) # there is some delay to update the history file, so 30 sec wait give it enough time to make sure your last url get logged
shutil.copy(source_file,destination_file) # copying the file.
con = sqlite3.connect('C:\\Users\\{user}\\Downloads\\History')#connecting to browser history
cursor = con.execute("SELECT * FROM urls")
names = [description[0] for description in cursor.description]
urls = cursor.fetchall()
con.close()
df_history = pd.DataFrame(urls,columns=names)
last_url = df_history.loc[len(df_history)-1,'url']
print(last_url)


>>https://twitter.com/ozanbayram01

我编写了以下函数来从一个简短的 URL (bit.ly,t.co,...)获取完整的 URL

import requests


def expand_short_url(url):
r = requests.head(url, allow_redirects=False)
r.raise_for_status()
if 300 < r.status_code < 400:
url = r.headers.get('Location', url)


return url

用法(短 URL 是这个问题的 URL) :

short_url = 'https://tinyurl.com/' + '4d4ytpbx'
full_url = expand_short_url(short_url)
print(full_url)

产出:

https://stackoverflow.com/questions/20475552/python-requests-library-redirect-new-url

所有的答案都适用于存在最终 URL/工作正常的情况。 如果最终的 URL 看起来不起作用,那么下面就是捕获所有重定向的方法。 有一种情况下,最终的 URL 不再工作,其他方式,如网址历史记录给出错误。
代码片段

long_url = ''
url = 'http://example.com/bla-bla'
try:
while True:
long_url = requests.head(url).headers['location']
print(long_url)
url = long_url
except:
print(long_url)