使用Python进行URL编码/解码

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

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

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

3)我调用urllib.quote(myString,'')存储的值,大概是% – 转义他们运输到客户端,所以客户端可以不正当地逃脱他们。

结果是,当我尝试logging%转义的结果时,出现exception。 是否有一些关键的步骤,我忽略了需要适用于存储的值与\ u和\ x格式为了正确地将其转换为通过HTTP发送?

更新 :标记为下面的答案的build议为我工作。 不过,我正在提供一些更新来解决下面的评论。

我收到的例外引用了\u20ac一个问题。 我不知道这是否是一个具体的问题,而不是它是string中的第一个Unicode字符。

这个字符是“欧元”符号的统一码。 我基本上发现我会遇到问题,除非我使用urllib2 quote方法。

编码一个“原始”unicode的url实际上并不合理。 你需要做的是.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' 

请记住,如果您正在进行debugging或其他任何操作,您将需要同时将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()是使用非ASCII字符的Python标准urllib.quote()和urllib.quote_plus()的版本。 (数据在编码之前转换为UTF-8。)

如果您正在使用任何进一步的引号或编码,请勿小心,否则请小心。

我想第二个pycruft的评论。 networking协议已经发展了几十年,处理各种各样的惯例可能是麻烦的。 现在,URL恰好不是为字符而定义的,而是仅用于字节(八位字节)。 作为一个历史巧合,URL是您只能假设的地方之一,但不能强制或安全地期望编码存在。 然而,在这里有一个比其他编码更喜欢latin-1和utf-8的约定。 有一段时间,它看起来像“ unicode百分之一百逃跑 ”将是未来,但他们从来没有抓住过。

在这个领域中unicode对象和八位字节字符之间的区别(在Python <3.0;也就是说,令人困惑的是, str unicode对象和Python> = 3.0中的bytes / bytes bytearray对象)之间的区别是非常重要的。 不幸的是,根据我的经验,很多原因很难在Python 2.x中完全分离这两个概念。

甚至更多的OT,当你想接收第三方的HTTP请求时,你不能绝对依靠以百分比转义的,UTF-8编码的八位字节发送的URL:这里可能偶尔有%uxxxx转义,至lessfirefox 2.x用于在可能的情况下将URL编码为latin-1,而只在必要时用作utf-8。

你用stdlib运气不好,urllib.quote不能用于unicode。 如果您使用的是Django,您可以使用django.utils.http.urlquote,它可以与unicode