python url unquote后跟unicode decod

2024-06-01 08:16:57 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个类似'%C3%A7%C3%B6asd+fjkls%25asd'的unicode字符串,我想解码这个字符串。
我用了urllib.unquote_plus(str)但它工作不正常。

  • 应输入:çöasd+fjkls%asd
  • 结果:çöasd fjkls%asd

双编码utf-8字符(%C3%A7%C3%B6)解码错误。
我的python版本是linux发行版下的2.7。 获得预期结果的最佳方法是什么?


Tags: 字符串编码错误unicodeplusurllib解码字符
3条回答

再次尝试urllib2

print urllib2.unquote('%C3%A7%C3%B6asd+fjkls%25asd')

你有3到4到5个问题。。。但是repr()unicodedata.name()是你的朋友;他们毫不含糊地向你展示了你所拥有的一切,没有不同控制台编码的人在交流print fubar的结果时产生的混乱。

摘要:要么(a)从unicode对象开始并对其应用unquote函数,要么(b)从str对象开始,并且控制台编码不是UTF-8。

如果像您所说的那样,从unicode对象开始:

>>> s0 = u'%C3%A7%C3%B6asd+fjkls%25asd'
>>> print repr(s0)
u'%C3%A7%C3%B6asd+fjkls%25asd'

这是偶然的胡说八道。如果对其应用urllibX.unquote_YYYY(),则会得到另一个无意义的unicode对象(u'\xc3\xa7\xc3\xb6asd+fjkls%asd'),这将导致打印时显示的症状。应立即将原始unicode对象转换为str对象:

>>> s1 = s0.encode('ascii')
>>> print repr(s1)
'%C3%A7%C3%B6asd+fjkls%25asd'

那么你应该取消引用它:

>>> import urllib2
>>> s2 = urllib2.unquote(s1)
>>> print repr(s2)
'\xc3\xa7\xc3\xb6asd+fjkls%asd'

看前面的4个字节,它是用UTF-8编码的。如果您这样做print s2,那么如果您的控制台期望UTF-8,那么它看起来是正常的,但是如果它期望ISO-8859-1(又称latin1),那么您将看到有症状的垃圾(第一个字符将是A-tilde)。让我们暂时停止这种想法,并将其转换为Unicode对象:

>>> s3 = s2.decode('utf8')
>>> print repr(s3)
u'\xe7\xf6asd+fjkls%asd'

检查一下看看我们到底有什么:

>>> import unicodedata
>>> for c in s3[:6]:
...     print repr(c), unicodedata.name(c)
...
u'\xe7' LATIN SMALL LETTER C WITH CEDILLA
u'\xf6' LATIN SMALL LETTER O WITH DIAERESIS
u'a' LATIN SMALL LETTER A
u's' LATIN SMALL LETTER S
u'd' LATIN SMALL LETTER D
u'+' PLUS SIGN

看起来像你说的你所期望的。现在我们来讨论在您的控制台上显示它的问题。注意:当你看到“cp850”时不要惊慌失措;我做这件事很方便,只是碰巧在Windows上的命令提示符下。

>>> import sys
>>> sys.stdout.encoding
'cp850'
>>> print s3
çöasd+fjkls%asd

注意:unicode对象是使用sys.stdout.encoding显式编码的。幸运的是,s3中的所有unicode字符都可以用该编码(以及cp1252和latin1)表示。

使用unquoteunquote_plus将为您提供一个字节字符串。如果需要Unicode字符串,则必须将字节字符串解码为Unicode:

>>> print(urllib.unquote_plus('%C3%A7%C3%B6asd+fjkls%25asd').decode('utf8'))
çöasd fjkls%asd
>>> 

与之相比:

>>> print(urllib.unquote_plus('%C3%A7%C3%B6asd+fjkls%25asd'))
çöasd fjkls%asd
>>> 

注意,输入字符串必须是字节字符串:如果您将unicode传递给unquote/unquote_plus,那么您将得到一点混乱。如果是这样,请先对其进行编码:

>>> print(urllib.unquote_plus(u'%C3%A7%C3%B6asd+fjkls%25asd'.encode('ascii')).decode('utf8'))
çöasd fjkls%asd

相关问题 更多 >