在 Python 2.6.5 中,我可以为 urllib.quote 和 urllib.unquote 使用 unicode-ready 替代品吗?

Posted

技术标签:

【中文标题】在 Python 2.6.5 中,我可以为 urllib.quote 和 urllib.unquote 使用 unicode-ready 替代品吗?【英文标题】:Is there a unicode-ready substitute I can use for urllib.quote and urllib.unquote in Python 2.6.5? 【发布时间】:2011-07-30 07:03:58 【问题描述】:

Python 的 urllib.quoteurllib.unquote 在 Python 2.6.5 中无法正确处理 Unicode。这就是发生的事情:

In [5]: print urllib.unquote(urllib.quote(u'Cataño'))
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)

/home/kkinder/<ipython console> in <module>()

/usr/lib/python2.6/urllib.pyc in quote(s, safe)
   1222             safe_map[c] = (c in safe) and c or ('%%%02X' % i)
   1223         _safemaps[cachekey] = safe_map
-> 1224     res = map(safe_map.__getitem__, s)
   1225     return ''.join(res)
   1226 

KeyError: u'\xc3'

将值编码为 UTF8 也不起作用:

In [6]: print urllib.unquote(urllib.quote(u'Cataño'.encode('utf8')))
Cataño

它被认为是一个错误和there is a fix,但不适用于我的 Python 版本。

我想要的是类似于 urllib.quote/urllib.unquote 的东西,但可以正确处理 unicode 变量,这样这段代码就可以工作:

decode_url(encode_url(u'Cataño')) == u'Cataño'

有什么建议吗?

【问题讨论】:

幸运的是,OP 似乎有些困惑:正如回溯所示,这确实是 2.6。 我不知道你到底发生了什么,但我将你的引用/取消引用示例逐字粘贴到我的解释器 python2.6 中,它正确打印了 Cataño。 啊,纳米,bobince 已经在下面回答了。 【参考方案1】:

"""将值编码为 UTF8 也不起作用""" ...您的代码结果是一个 str 对象,猜测似乎是用 UTF-8 编码的输入。您需要对其进行解码或定义“不起作用”——您希望 做什么

注意:为了让我们无需猜测您的终端编码和数据类型,请使用print repr(whatever) 而不是print whatever

>>> # Python 2.6.6
... from urllib import quote, unquote
>>> s = u"Cata\xf1o"
>>> q = quote(s.encode('utf8'))
>>> u = unquote(q).decode('utf8')
>>> for x in (s, q, u):
...     print repr(x)
...
u'Cata\xf1o'
'Cata%C3%B1o'
u'Cata\xf1o'
>>>

比较:

>>> # Python 3.2
... from urllib.parse import quote, unquote
>>> s = "Cata\xf1o"
>>> q = quote(s)
>>> u = unquote(q)
>>> for x in (s, q, u):
...     print(ascii(x))
...
'Cata\xf1o'
'Cata%C3%B1o'
'Cata\xf1o'
>>>

【讨论】:

很简单,我希望 unqoute 的结果是我发送给 quote() 的结果。我发现 urllib 基本上需要一个 latin1 编码。 @Ken:我希望latin1 是偶然的,而不是预期的。无论如何,latin 通常不会处理您的问题。您还应该期望quote() 的结果将给出“正确”的答案——因此我与 Python 3.2 进行了比较。 Python 2.6.6 引用使用latin1 而不是utf8 产生'Cata%F1o' 这完全解决了我的问题:q = quote(s.encode('utf8'))【参考方案2】:

Python 的 urllib.quote 和 urllib.unquote 不能正确处理 Unicode

urllib 根本不处理 Unicode。根据定义,URL 不包含非 ASCII 字符。当您处理urllib 时,您应该只使用字节字符串。如果您希望它们代表 Unicode 字符,则必须手动对其进行编码和解码。

IRIs 可以包含非 ASCII 字符,将它们编码为 UTF-8 序列,但 Python 目前没有irilib

将值编码为 UTF8 也不起作用:

In [6]: print urllib.unquote(urllib.quote(u'Cataño'.encode('utf8')))
Cataño

啊,现在您在控制台中输入 Unicode,并在控制台中输入 print-Unicode。这通常是不可靠的,尤其是在 Windows 和您的情况下with the IPython console。

用反斜杠序列将它输入很长的路,您可以更容易地看到urllib 位确实有效:

>>> u'Cata\u00F1o'.encode('utf-8')
'Cata\xC3\xB1o'
>>> urllib.quote(_)
'Cata%C3%B1o'

>>> urllib.unquote(_)
'Cata\xC3\xB1o'
>>> _.decode('utf-8')
u'Cata\xF1o'

【讨论】:

实际上问题是我在使用 UTF8 进行测试时从未解码过 URL。简单的错误。【参考方案3】:

我也遇到了同样的问题,用辅助函数处理非ascii和urllib.urlencode函数(包括quote和unquote):

def utf8_urlencode(params):
    import urllib as u
    # problem: u.urlencode(params.items()) is not unicode-safe. Must encode all params strings as utf8 first.
    # UTF-8 encodes all the keys and values in params dictionary
    for k,v in params.items():
        # TRY urllib.unquote_plus(artist.encode('utf-8')).decode('utf-8')
        if type(v) in (int, long, float):
            params[k] = v
        else:
            try:
                params[k.encode('utf-8')] = v.encode('utf-8')
            except Exception as e:
                logging.warning( '**ERROR utf8_urlencode ERROR** %s' % e )
    return u.urlencode(params.items()).decode('utf-8')

取自Unicode URL encode / decode with Python

【讨论】:

【参考方案4】:

所以我遇到了同样的问题:我想将查询参数放在 url 中,但其中一些包含奇怪的字符(变音符号)。

处理编码会导致 url 乱七八糟,而且很脆弱。

我的解决方案是将每个重音/奇怪的 unicode 字符替换为其 ascii 等效字符。感谢unidecode,这很简单:What is the best way to remove accents in a Python unicode string?

pip install unidecode

然后

from unidecode import unidecode
print unidecode(u"éèê") 
# prints eee

所以我有一个干净的网址。也适用于中文等。

【讨论】:

以上是关于在 Python 2.6.5 中,我可以为 urllib.quote 和 urllib.unquote 使用 unicode-ready 替代品吗?的主要内容,如果未能解决你的问题,请参考以下文章

如何将整数转换为 Python 中最短的 url 安全字符串?

在 Python 中提取 URL

有啥方法可以使用 python 中的注释在 django 中编写 URL

如何在python,django中将url解码为路径

Python:在将URL结果转换为JSON文件时,在每个项目后添加延迟

Python中Flask框架的变量和函数