python - HTTP 301 重定向 url 编码问题
问题描述
我正在使用 Python 的 requests.get() 来获取一些 Facebook 个人资料 HTML。其中一些将请求重定向到新的 url。当这个新的 url 包含特殊字符时,例如'á',request.get() 方法进入重定向循环,直到引发异常。我找到了一种解决方法来更正重定向 url 字符串,该字符串位于“Location”键下的响应标头中,但它远非一个优雅的解决方案。
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)
必须有更好的方法来处理这个问题。我尝试了一堆不同的标头,并使用了 requests.Session(),但它们都不起作用。提前感谢您的帮助。
解决方案
标头通常编码为 Latin-1,因此这就是requests
用于解码所有标头的方法。但是,在实践中,Location 标头通常使用 UTF-8 来代替。您所看到的是Mojibake,在本例中是解码为 Latin-1 的 UTF-8 数据。
从 requests 2.14.0(2017 年 5 月发布)开始,该库专门将 Location 标头解码为 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(...)
推荐阅读
- python - 将日期时间提取到年份但导致浮动
- javascript - NextJS:动态 router.pathname 不显示路径,而是显示文件名 - 如何获取路径中的单词?
- python - Azure 自托管代理运行 pytest
- c# - 在类库中使用 API 接口,在 API 接口中使用类库?
- advanced-installer - 高级安装程序:在完成查询之前运行 sql 查询脚本
- python-3.x - 如何将 mongoengine.Document 的继承添加到现有类中
- reactjs - 在反应中带来关于过滤器的最大数据记录
- javascript - 使用 querySelector 按 ID 定位特定表中的行
- android - 使用内容解析器 Android 打开文件
- reactjs - 从导航组件跳过指向主要内容的链接