使用Python进行URL编码/解码

时间:2010-08-25 05:42:08

标签: python url-encoding

我正在尝试编码和存储,并在Python中解码参数并在此过程中丢失。以下是我的步骤:

1)我使用google toolkit的gtm_stringByEscapingForURLArgument正确转换NSString以传入HTTP参数。

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

3)我在该存储的值上调用urllib.quote(myString,''),大概是为了将它们转移到客户端,以便客户端可以解除它们的转义。

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

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

我收到的例外情况引用了\u20ac的问题。我不知道具体是否是一个问题,而不是它是字符串中第一个unicode字符的事实。

\u20ac char是'euro'符号的unicode。除非我使用urllib2 quote方法,否则我基本上发现我遇到了问题。

3 个答案:

答案 0 :(得分:70)

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 functions所做的。

  

功能   django.utils.http.urlquote()和   django.utils.http.urlquote_plus()是   Python标准的版本   urllib.quote()和urllib.quote_plus()   使用非ASCII字符。   (数据先前转换为UTF-8   编码。)

如果您使用任何进一步的引用或编码不要破坏东西,请小心。

答案 1 :(得分:4)

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

在这个领域迂回挑剔关于unicode个对象和八位位组str之间的区别是非常重要的(在Python&lt; 3.0;那个,令人困惑的是,str unicode Python中的对象和bytes / bytearray个对象&gt; = 3.0)。不幸的是,根据我的经验,出于多种原因很难将Python 2.x中的两个概念完全分开。

更多OT,当您想要接收第三方HTTP请求时,您不能完全依赖以百分比转义,utf-8编码的八位字节发送的URL:偶尔可能有%uxxxx在那里逃避,并且至少firefox 2.x用于在可能的情况下将URL编码为latin-1,并且仅在必要时将utf-8编码为utf-8。

答案 2 :(得分:2)

你运气不好stdlib,urllib.quote不适用于unicode。如果你使用django,你可以使用django.utils.http.urlquote,它可以正常使用unicode