gpt4 book ai didi

Python 请求奇怪的 URL %-Encoding

转载 作者:行者123 更新时间:2023-11-28 22:29:14 24 4
gpt4 key购买 nike

使用 Python 3.6.1,Requests 2.13.0,我对请求的 URL 进行了奇怪的编码。我有一个在查询字符串中包含中文字符的 URL,例如 huà 话用,应该 %-encode 为 hu%C3%A0%20%E8%A9%B1%20% E7%94%A8 甚至 hu%C3%A0+%E8%A9%B1+%E7%94%A8,但由于某种原因,它是 %-encoding 到 hu %C3%83%C2%A0%20%C3%A8%C2%A9%C2%B1%20%C3%A7%C2%94%C2%A8。这是不正确的。我一直在使用 http://r12a.github.io/apps/conversion/帮助我处理编码的页面。我还使用了 JavaScript encodeURI 和 PHP urlencode 并且没有得到任何接近我看到的 Requests 库所做的事情。

我是不是做错了什么导致编码相差太远?

更新:我研究了 Mojibake 编码并深入研究了 Requests 库,发现了问题所在,但我仍然不确定如何解决它。

我正在对内部服务器进行调用,使用简单的 .get(url) 调用。调用转到服务器并获得重定向响应。重定向页面的 header 中有一个 meta charset="UTF-8",其中列出的 URL 是正确的。离开服务器的 location header 是可以的;它被编码为 UTF-8 并且 Content-Type header 上有一个 charset=UTF-8。但是,当我在 Python 中调试重定向响应时,我注意到响应对象上的 header 不正确,它似乎没有被正确解码。 headers 属性在 location 中包含此内容:huÃ\xa0 話 ç\x94。如上所说,应该解码为:huà话用。因此,那个奇怪的 URL 查询字符串的 % 由 Requests 编码并设置回服务器,然后服务器拒绝该 URL(很明显)。

我能做些什么来防止 Requests 把事情搞砸吗?或者让它正确解码 location header ? Web 浏览器似乎没有这方面的问题。

最佳答案

你有一个 Mojibake编码。编码的字节是 UTF-8 字节的 Latin-1 解释:

>>> from urllib.parse import quote
>>> text = 'huà 話 用'
>>> quote(text)
'hu%C3%A0%20%E8%A9%B1%20%E7%94%A8'
>>> quote(text.encode('utf8').decode('latin1'))
'hu%C3%83%C2%A0%20%C3%A8%C2%A9%C2%B1%20%C3%A7%C2%94%C2%A8'

您可以通过再次手动编码为 Latin-1,然后从 UTF-8 解码来反转该过程:

>>> unquote('hu%C3%83%C2%A0%20%C3%A8%C2%A9%C2%B1%20%C3%A7%C2%94%C2%A8').encode('latin1').decode('utf8')
'huà 話 用'

或者您可以使用 ftfy library自动修复错误的编码(ftfy 通常做得更好,尤其是当 Windows 代码页涉及到 Mojibake 时):

>>> from ftfy import fix_text
>>> fix_text(unquote('hu%C3%83%C2%A0%20%C3%A8%C2%A9%C2%B1%20%C3%A7%C2%94%C2%A8'))
'huà 話 用'

关于 URL 的来源,你是这样说的:

The location header leaving the server is ok; it is encoded as UTF-8

那是你的问题,就在那里。 HTTP header 始终编码为 Latin-1(*)。服务器必须将 Location header 设置为完全百分比编码的 URL,以便所有 UTF-8 字节都表示为 %HH 转义序列。这些只是 ASCII 字符,完美保存在 Latin-1 上下文中。

如果您的服务器将 header 作为未转义的 UTF-8 字节发送,则 HTTP 客户端(包括 requests)会将其解码为 Latin-1 而不是导致您观察到的确切 Mojibake 问题。由于 URL 包含无效的 URL 字符,requests 将 Mojibake 结果转义为百分比编码版本。


(*) 实际上,Location header 应该是 absoluteURI as per RFC2396它始终是 ASCII(7 位)干净数据,但由于某些其他 HTTP header 允许“描述性”文本,因此 Latin-1 (ISO-8859-1) 是 header 数据可接受的默认编码。查看TEXT rule in section 2.2 of the HTTP/1.1 RFC , 和 http.client module在解码任何 header 中的非 ASCII 数据时,最终解码 requests 的 header 在这方面遵循此 RFC。仅当按照 the Message Header Extensions RFC 2047 包装时,您才能提供非 Latin-1 数据,但这不适用于 Location header 。

关于Python 请求奇怪的 URL %-Encoding,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43188661/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com