【问题标题】:Python 3.x requests redirect with unicode characterPython 3.x 请求使用 Unicode 字符重定向
【发布时间】:2018-04-17 05:23:45
【问题描述】:

我正在尝试在 Python 3.x 中使用 requests.get() 获取以下 URL:http://www.finanzen.net/suchergebnis.asp?strSuchString=DE0005933931(此 URL 由带有搜索字符串 DE0005933931 的基本 URL 组成。

请求被重定向(通过 HTTP 状态代码 301)到浏览器中的 http://www.finanzen.net/etf/ishares_core_dax%AE_ucits_etf_de(在 URL 中包含 character 0xAE 字符 ®)。将 requests.get() 与重定向 URL 一起使用也可以。

当尝试使用 Python 2.7 获取搜索字符串 URL 时,一切正常,我得到重定向的响应,使用 Python 3.x 我得到以下错误:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xae in position 21: invalid start byte

测试这个的代码sn-p:

import requests

url_1 = 'http://www.finanzen.net/suchergebnis.asp?strSuchString=LU0274208692'
# redirected to http://www.finanzen.net/etf/db_x-trackers_msci_world_index_ucits_etf_1c
url_2 = 'http://www.finanzen.net/suchergebnis.asp?strSuchString=DE0005933931'
# redirected to http://www.finanzen.net/etf/ishares_core_dax%AE_ucits_etf_de

print(requests.get(url_1).status_code)  # working
print(requests.get(url_2).status_code)  # error with Python 3.x

更多信息:

  • 我正在使用带有requests.__version__ = '2.18.4' 的 Python 3.6.3 在 Windows 7 上工作,但我 使用其他 Python 版本(3.4、3.5)也会出现同样的错误。
  • 使用其他搜索字符串,一切都适用于 Python 3.x, 例如 http://www.finanzen.net/suchergebnis.asp?strSuchString=LU0274208692
  • 有趣的是,我什至得到一个Internal Server Errorhttps://www.hurl.it 试图获取上述URL。也许这不是 Python 的问题。

任何想法,为什么这在 Python 2.7 中有效,但在 Python 3.x 中无效,我能做些什么?

【问题讨论】:

  • 你用的是linux还是mac?
  • requests.get("http://www.finanzen.net/etf/ishares_core_dax%AE_ucits_etf_de") 为我返回成功响应 (<Response [200]>),刚刚在 Python 3.6.3 上测试,请求版本 2.18.4。
  • 是的,这行得通。但是,使用搜索 URL 不起作用。我将此添加到问题中。
  • 我使用的是 Windows 7,已添加到问题中。
  • 是的,我可以确认搜索 URL 为我返回了同样的错误。

标签: python python-3.x unicode character-encoding python-requests


【解决方案1】:

服务器响应一个编码为 Latin-1 的 URL,该 URL 不是 URL 编码;非 ASCII 字节显示为 0x?? 十六进制转义:

Location: /etf/ishares_core_dax0xAE_ucits_etf_de

那里的0xAE字节不是一个有效的URL字符;服务器在这里违反标准。他们应该发送的是

Location: /etf/ishares_core_dax%AE_ucits_etf_de

Location: /etf/ishares_core_dax%C2%AE_ucits_etf_de

对 URL 的 Latin-1 或 UTF-8 编码使用转义数据。

我们可以修补requests,使其在面对此错误时更加健壮,方法是保持Location 标头不变:

from requests.sessions import SessionRedirectMixin

def get_redirect_target(
        self, resp, _orig=SessionRedirectMixin.get_redirect_target):
    try:
        return _orig(self, resp)
    except UnicodeDecodeError:
        return resp.headers['location']

SessionRedirectMixin.get_redirect_target = get_redirect_target

应用此补丁后,重定向按预期工作。

created a pull request 来改进位置处理。

【讨论】:

  • 根本原因是这里的设计决策:github.com/requests/requests/blob/master/requests/…
  • @Tomalak:这个设计没有错。服务器在该位置发送一个无效的 URL。
  • @Tomalak:不过,设计可能会更健壮。
  • 嗯,这肯定是有问题的。你不能简单地用手指交叉重新编码一个字符串而没有任何错误处理。
  • 感谢@MartijnPieters 的解释和补丁——它有效。尝试将其纳入请求本身是否有意义?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-20
  • 2017-11-19
  • 1970-01-01
  • 2011-06-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多