【问题标题】:Python urlencode special characterPython urlencode 特殊字符
【发布时间】:2017-09-06 14:23:17
【问题描述】:

我这里有这个变量

reload(sys)
sys.setdefaultencoding('utf8') 
foo = u'"Esp\xc3\xadrito"'

翻译为“Espírito”。但是当我像这样将我的变量传递给 urlencode 时

urllib.urlencode({"q": foo}) # q=%22Esp%C3%83%C2%ADrito%22'

特殊字符在 URL 中被错误地“表示”。

我应该如何解决这个问题?

【问题讨论】:

  • 这是 Python2 还是 3?
  • @IronFist Python2。该函数在 Python 3 中称为 urllib.parse.urlencode
  • 是的,它的 Python 2.7。知道出了什么问题吗?当我将 q=%22Esp%C3%83%C2%ADrito%22' 放在解码器(例如meyerweb.com/eric/tools/dencoder)上时,解码后的值变为 q="EspÃrito"' 这是错误的。
  • 你说是因为百分比表示还是因为不是实际编码?
  • 我想将“Espírito”作为查询参数发送到 endoint,但在我对其进行 urlencode 后,它变成了“Espírito”。 “i”变成了“A”,这是无意的。

标签: python unicode encoding python-2.x urlencode


【解决方案1】:

"Espírito" 的编码错误,我不知道你从哪里得到的,但这是正确的:

>>> s = u'"Espírito"'
>>> 
>>> s
u'"Esp\xedrito"'

然后编码您的查询:

>>> u.urlencode({'q':s.encode('utf-8')})
'q=%22Esp%C3%ADrito%22'

这应该会给你正确的字符串编码。

编辑:这是关于您的查询字符串的正确编码,演示:

>>> s = u'"Espírito"'
>>> print s
"Espírito"
>>> s.encode('utf-8')
'"Esp\xc3\xadrito"'
>>> s.encode('latin-1')
'"Esp\xedrito"'
>>> 
>>> print "Esp\xc3\xadrito"
Espí­rito
>>> print "Esp\xedrito"
Espírito

这清楚地表明您的字符串的正确编码是最有可能 latin-1(甚至cp1252 也可以),据我所知, urlparse.parse_qs 采用默认编码 utf-8 或您的系统默认编码,根据您的帖子,您也将其设置为 utf-8

有趣的是,我正在您在评论中提供的查询,我得到了这个:

>>> q = "q=Esp%C3%ADrito"
>>> 
>>> p = urlparse.parse_qs(q)
>>> p['q'][0].decode('utf-8')
u'Esp\xedrito'
>>>
>>> p['q'][0].decode('latin-1')
u'Esp\xc3\xadrito'

#Clearly not ASCII encoding.
>>> p['q'][0].decode()

Traceback (most recent call last):
  File "<pyshell#320>", line 1, in <module>
    p['q'][0].decode()
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 3: ordinal not in range(128)
>>> 
>>> p['q'][0]
'Esp\xc3\xadrito'
>>> print p['q'][0]
Espírito
>>> print p['q'][0].decode('utf-8')
Espírito

【讨论】:

  • 对不起,我应该更清楚地解释我如何获得 \xc3\xad。它是一条微服务管道,实际上首先我得到了“q=Esp%C3%ADrito”(urlencoded)然后我在上面运行了 urlparse.parse_qs 然后我得到了 u'"Esp\xc3\xadrito"'
  • 无论如何我认为这是我的 Python 问题,当我运行 s = u'"Espírito"' 然后 s 在交互模式下我得到 u'"Esp\xc3\xadrito"' 而不是 u'"Esp \xedrito"' 就像你做的那样。
  • 可能,它需要更多调查urlparse如何处理unicode查询,从它获取编码方案的地方,我试图查看urlparse文档,但没有找到任何线索。跨度>
  • 坦率地说,u"Esp\u00edrito" 是编码此字符串的正确方法。您不能在 u"..." 字符串中有意义地使用 UTF-8;根据定义,这些字符串是 Unicode,不能适应任何其他编码(尽管您有时会看到人们出于各种原因以创造性的方式解决这一事实)。 UTF-8 中的 字节字符串 可以转换为 Unicode 字符串,反之亦然,但它们是您似乎混淆的两种不同表示形式。
【解决方案2】:

urlliburlparse 似乎可以在 Python 2 中处理字节字符串。要获取 unicode 字符串,请使用 utf-8 进行编码和解码。

这是一个往返的例子:

data = { 'q': u'Espírito'}

# to query string:
bdata = {k: v.encode('utf-8') for k, v in data.iteritems()}
qs = urllib.urlencode(bdata)

# qs = 'q=Esp%C3%ADrito'

# to dict:
bdata = urlparse.parse_qs(qs)
data = { k: map(lambda s: s.decode('utf-8'), v)
            for k, v in bdata.iteritems() }

# data = {'q': [u'Espídrito']}

注意转义序列的不同含义:在'Esp\xc3\xadrito'(一个字符串)中,它们代表字节,而在u'"Esp\xedrito"'(一个unicode对象)中,它们代表Unicode代码点。

【讨论】:

    猜你喜欢
    • 2016-10-19
    • 2015-03-10
    • 2014-07-27
    • 2013-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-18
    • 1970-01-01
    相关资源
    最近更新 更多