48

我正在尝试在 Python 中编码、存储和解码参数,并在此过程中迷路。这是我的步骤:

1)我使用谷歌工具包gtm_stringByEscapingForURLArgument正确转换 NSString 以传递到 HTTP 参数。

2)在我的服务器(python)上,我将这些字符串参数存储为类似的东西u'1234567890-/:;()$&@".,?!\'[]{}#%^*+=_\\|~<>\u20ac\xa3\xa5\u2022.,?!\''(请注意,这些是“123”视图和“#+=”视图中 iphone 键盘上的标准键,其中的\u\x字符一些货币前缀,如英镑、日元等)

3)我调用urllib.quote(myString,'')该存储值,大概是为了将它们转义以传输到客户端,以便客户端可以不百分比地转义它们。

结果是当我尝试记录 % 转义的结果时出现异常。是否有一些我忽略的关键步骤需要应用于具有 \u 和 \x 格式的存储值,以便正确转换它以通过 http 发送?

更新:标记为以下答案的建议对我有用。不过,我正在提供一些更新以解决下面的评论以使其完整。

我收到的异常引用了\u20ac. 我不知道这是否是一个问题,而不是它是字符串中的第一个 unicode 字符这一事实。

\u20ac字符是“欧元”符号的 unicode。我基本上发现除非我使用 urllib2quote方法,否则我会遇到问题。

4

3 回答 3

71

url 编码一个“原始”的 unicode 并没有真正的意义。你需要做的是.encode("utf8")首先让你有一个已知的字节编码,然后.quote()是。

输出不是很漂亮,但它应该是正确的 uri 编码。

>>> s = u'1234567890-/:;()$&@".,?!\'[]{}#%^*+=_\|~<>\u20ac\xa3\xa5\u2022.,?!\''
>>> urllib2.quote(s.encode("utf8"))
'1234567890-/%3A%3B%28%29%24%26%40%22.%2C%3F%21%27%5B%5D%7B%7D%23%25%5E%2A%2B%3D_%5C%7C%7E%3C%3E%E2%82%AC%C2%A3%C2%A5%E2%80%A2.%2C%3F%21%27'

unquote()请记住,如果您正在调试或其他任何事情,您将需要这两者decode()才能正确打印出来。

>>> print urllib2.unquote(urllib2.quote(s.encode("utf8")))
1234567890-/:;()$&@".,?!'[]{}#%^*+=_\|~<>€£¥•.,?!'
>>> # oops, nasty  means we've got a utf8 byte stream being treated as an ascii stream
>>> print urllib2.unquote(urllib2.quote(s.encode("utf8"))).decode("utf8")
1234567890-/:;()$&@".,?!'[]{}#%^*+=_\|~<>€£¥•.,?!'

事实上,这就是另一个答案中提到的django 函数的作用。

函数 django.utils.http.urlquote() 和 django.utils.http.urlquote_plus() 是 Python 标准 urllib.quote() 和 urllib.quote_plus() 的版本,可用于非 ASCII 字符。(数据在编码之前转换为 UTF-8。)

如果您要应用任何进一步的引号或编码以不破坏事物,请小心。

于 2010-08-25T11:48:13.973 回答
4

我想第二次 pycruft 的评论。Web 协议已经发展了几十年,处理各种约定可能很麻烦。现在 URL 碰巧没有明确地为字符定义,而只是为字节(八位字节)定义。作为一个历史巧合,URL 是您只能假设但不能强制执行或安全地期望存在编码的地方之一。但是,这里有一个惯例是更喜欢 latin-1 和 utf-8 而不是其他编码。有一段时间,看起来 ' unicode percent escapes ' 会成为未来,但他们从未流行起来。

unicode在这个领域对对象和八位字节之间的区别str(在 Python < 3.0 中;令人困惑的是,在 Python >= 3.0 中的strunicode 对象和bytes/对象)之间的区别保持迂腐的挑剔是至关重要的。bytearray不幸的是,根据我的经验,在 Python 2.x 中完全区分这两个概念有很多原因。

更 OT,当您想要接收第三方 HTTP 请求时,您不能绝对依赖以百分比转义、utf-8 编码的八位字节发送的 URL:其中可能有偶尔的%uxxxx转义,至少 firefox 2.x 曾在可能的情况下将 URL 编码为 latin-1,仅在必要时将其编码为 utf-8。

于 2010-08-25T14:40:28.807 回答
2

您对 stdlib 不走运,urllib.quote 不适用于 unicode。如果您使用的是 django,则可以使用 django.utils.http.urlquote 与 unicode 一起正常工作

于 2010-08-25T06:33:23.977 回答