在javascript中编码了一个unicode字符串之后,我如何才能在python中对其进行解码?

Having encoded a unicode string in javascript, how can I decode it in Python?

App Engine平台:webapp WSGI的CGI框架:/ /

在我的客户端(JS)、I(URL url结构带有一concatenating Unicode字符串:

1
http://www.foo.com/地震

然后我打电话给encodeuri to get

1
http://www.foo.com/%E5%9C%B0%E9%9C%87

我把这个HTML表单中的值。

PayPal的形式提交给大家,在我已经设置到UTF-8编码。

然后通过PayPal的IPN)使请求的URL后说。

在我的服务器端,wsgiapplication tries提取使用的Unicode字符串的正则表达式,我定义为:

1
(r'/paypal-listener/(.+?)', c.PayPalIPNListener)

我尝试把它通过调用解码

1
query = unquote_plus(query).decode('utf-8')

(或变异),但我得到的错误

/paypal-listener/%E5%9C%B0%E9%9C%87

... (ommited) ...

'ascii' codec can't encode characters
in position 0-1: ordinal not in
range(128)

(在第一行是请求的URL)

当我检查的长度query说,Python,它已长到18岁,这表明我是5 % % % % % E9 9C条,9C条为87 %’中未被编码的反正。


原则上,这应该起作用:

1
2
>>> urllib.unquote_plus('http://www.foo.com/%E5%9C%B0%E9%9C%87').decode('utf-8')
u'http://www.foo.com/\u5730\u9707'

但是,请注意:

  • unquote_plus用于application/x-form-www-urlencoded数据,如已发布的表单和查询字符串参数。在URL的路径部分,+表示文字加号,而不是空格,因此您应该在这里使用普通的unquote

  • 一般来说,你不应该引用整个URL。URL组件中具有特殊含义的字符将丢失。您应该将URL拆分为多个部分,获取您感兴趣的单一路径名组件(%E5%9C%B0%E9%9C%87),然后将其取消引用。

  • (如果你想把一个URI完全转换成一个IRI,比如http://www.foo.com/地震,事情会复杂一些。只有IRI的path/query/fragment部分是utf-8-%编码的;域名使用oddball的"punycode"idn方案在unicode和字节之间映射。)

    This gets received in my python server side.

    服务器端到底是什么?服务器、网关、框架?你是如何得到url变量的?

    您似乎得到了一个UnicodeEncodeError,这是关于unquote函数输入中意外的非ASCII字符,根本不是一个解码问题。因此,我建议已经有东西将URL的路径部分解码为某种Unicode字符串。让我们看看这个变量的repr

    不幸的是,一些Web服务器存在一些严重的问题,这些问题使得在URL的路径名部分使用Unicode非常不可靠,不仅仅是在Python中,而且通常情况下。

    主要问题是,PATH_INFO变量(由cgi规范定义,随后由wsgi定义)要预解码。这是一个可怕的错误,部分原因是上面的问题(1),这意味着在路径部分无法获得%2F,但更严重的是,解码%序列会引入一个超出应用程序控制的Unicode解码步骤。服务器环境在处理URL中非ascii %转义的方式上存在很大差异,通常无法重新创建Web浏览器传入的确切字节序列。

    IIS是一个特殊的问题,因为它将尝试默认将URL路径解析为utf-8,如果路径不是有效的utf-8序列,但没有告诉您,它将返回到非常不可靠的系统默认代码页(例如,在西Windows安装中的cp1252)。然后,在从环境变量映射中读取PATH_INFO中的任何非ASCII字符时,您可能会遇到相当严重的问题,因为Windows envvars是Unicode的,但被python 2和许多其他字符作为系统代码页中的字节访问。

    Apache通过提供一个额外的非标准环境REQUEST_URI,保存浏览器提交的原始、完全未编码的URL,从而缓解了这个问题,这很容易手动处理。但是,如果您使用的是URL重写或错误文档,则未映射的URL可能与您认为的不匹配。

    一些框架试图通过不同程度的成功来解决这些问题。WSGI 1.1有望在标准化这一点上有所突破,但与此同时,我们所处的实际位置是Unicode路径不会在任何地方都起作用,试图在一台服务器上修复它的黑客通常会在另一台服务器上破坏它。

    可以始终使用URL重写将Unicode路径转换为Unicode查询参数。由于QUERY_STRING环境变量不在应用程序外部解码,因此更容易预测处理。


    假设HTML页面是以UTF-8编码的,那么如果框架解码了URL百分比,那么它应该只是一个简单的path.decode('utf-8')

    如果没有,可以使用:

    • 如果URL是http://www.foo.com/地震,则返回urllib.unquote(path).decode('utf-8')
    • 如果您谈论的是通过Ajax或HTML
      发送的参数,则为urllib.unquote_plus(path).decode('utf-8')

    (见http://docs.python.org/library/urlib.html_urlib.unquote)

    编辑:如果您仍有问题,请向我们提供以下信息以帮助我们跟踪此问题:

    • 您在Google应用程序引擎内部使用的Web框架,例如django、webob、cgi等
    • 如何在应用程序中获取URL(如果可以,请添加一个简短的代码示例)
    • 添加http://www.foo.com/地震作为url
    • 尝试将其添加为URL并发布repr(url),这样我们就可以确保服务器不会将字符解码为拉丁语-1或Windows-1252:

      1
      http://foo.com/?¢£¤¥|§¨?a??-?ˉ°±23′μ?·?1o?????àá??????èéê?ìí??D?òó???×?ùú?üYT?àáa?????èéê?ìí??e?òó???÷?ùú?üyt?

    编辑2:查看它是一个实际的URL(而不是在查询部分,即不是http://www.foo.com/?param=%E5%9C%B0%E9%9C%87中),执行

    1
    query = unquote(query.encode('ascii')).decode('utf-8')

    可能是安全的。如果您正在解码实际的URL,应该是unquote,而不是unquote_plus。我不知道Google为什么把URL作为unicode对象来传递,但我怀疑传递给应用程序的实际URL会被windows-1252等解码。我有点担心,因为我认为它解码错误(即传递给GETPOST的参数),但从外观上看,它似乎没有做到这一点。


    在这种情况下,urllib.unquote()不喜欢unicode字符串。传递字节字符串,然后解码以获得Unicode。

    这工作:

    1
    2
    3
    4
    5
    >>> u = u'http://www.foo.com/%E5%9C%B0%E9%9C%87'
    >>> print urllib.unquote(u.encode('ascii'))
    http://www.foo.com/地震
    >>> print urllib.unquote(u.encode('ascii')).decode('utf-8')
    http://www.foo.com/地震

    这不是(另请参见urllib.unquote解码拉丁语1的百分比转义):

    1
    2
    >>> print urllib.unquote(u)
    http://www.foo.com/? °é

    解码已使用Unicode的字符串不起作用:

    1
    2
    3
    4
    5
    6
    7
    8
    >>> print urllib.unquote(u).decode('utf-8')
    Traceback (most recent call last):
      File"<input>", line 1, in <module>
      File".../lib/python2.6/encodings/utf_8.py", line
    16, in decode
        return codecs.utf_8_decode(input, errors, True)
    UnicodeEncodeError: 'ascii' codec can't encode characters in position 19-24: o
    rdinal not in range(128)


    通常有一个服务器端语言的函数来解码URL,也可能有一个在Python中。您也可以在您的案例中使用javascript的decodeURIComponent()函数。


    啊啊,可怕的

    'ascii' codec can't encode characters in position... ordinal not in range

    错误。在用Python处理日语等语言时不可避免…

    在这种情况下,这不是URL编码/解码问题。您的数据很可能已经解码并准备就绪。

    我试着摆脱"解码"的电话,看看会发生什么。如果你得到垃圾,但没有错误,这可能意味着人们发送给你的数据,在另一个可爱的日本具体编码:eucjp,iso-2022-jp,shift-jis,甚至可能是难以捉摸的iso-2022-jp-ext,这是目前只有很少在野外发现。不过,后一种情况似乎不大可能发生。

    edit:id还可以参考:编码/解码有什么区别?