HTTP 301重定向网址编码问题

问题描述 投票:1回答:1

我正在使用Python的requests.get()来获取一些Facebook个人资料HTML。其中一些将请求重定向到新的URL。当这个新url具有特殊字符(例如'á')时,request.get()方法将进入重定向循环,直到引发异常。我找到了一个解决方法来纠正重定向url字符串,在“位置”键下的响应标题中找到,但它远非优雅的解决方案。

import requests

# This case works. Response [200]
r = requests.get('https://www.facebook.com/profile.php?id=4')
print(r)

# This fails. Redirect location has special characters.
# raises requests.exceptions.TooManyRedirects: Exceeded 30 redirects.
not_working_url = 'https://www.facebook.com/profile.php?id=100010922979377'
try:
    r = requests.get(not_working_url)
except Exception as e:
    print(e)  # Exceeded 30 redirects.

# Workaround
r = requests.get(not_working_url,
                 allow_redirects=False)
redirect_url = r.headers["Location"]
print(redirect_url)
# "https://www.facebook.com/people/Tomás-Navarro-Febre/100010922979377"
# Special character 'á' on "/Tomás_Navarro_Febre/" is displayed as 'á'.

# This fixes the string.
redirect_url = redirect_url.encode('raw_unicode_escape').decode('utf-8')
print(redirect_url)
# "https://www.facebook.com/people/Tomás-Navarro-Febre/100010922979377"

# Now it works. Response [200]
r = requests.get(redirect_url)
print(r)

必须有更好的方法来解决这个问题。我尝试了一堆不同的头文件,并使用了request.Session(),但没有一个工作。在此先感谢您的帮助。

python html encoding python-requests mojibake
1个回答
1
投票

标头通常编码为Latin-1,因此requests用于解码所有标头。但是,实际上,Location标头通常使用UTF-8。你所看到的是一个Mojibake,在这种情况下,UTF-8数据被解码为Latin-1。

截至请求2.14.0(2017年5月发布),库specifically decodes the Location header as UTF-8,正是为了避免您遇到的问题。升级您的请求库。

如果无法升级,可以将Session类子类化为本地“修补”问题:

class UTF8RedirectingSession(requests.Session):
    def get_redirect_target(self, resp):
        if resp.is_redirect:
            return resp.headers['location'].encode('latin1').decode('utf8')
        return None

然后用

with UTF8RedirectingSession() as session:
    response = session.get(...)
© www.soinside.com 2019 - 2024. All rights reserved.