python url unquote后跟unicode解码

时间:2011-02-28 07:29:36

标签: url-encoding python-unicode

我有一个像'%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。 获得预期结果的最佳方法是什么?

6 个答案:

答案 0 :(得分:28)

您有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

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

答案 1 :(得分:12)

使用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

答案 2 :(得分:0)

再次尝试urllib2

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

答案 3 :(得分:0)

'%C3%A7%C3%B6asd + fjkls%25asd' - 这不是unicode字符串。

这是一个url编码的字符串。请改用urllib2.unquote()。

答案 4 :(得分:0)

你有一个双重问题:你的字符串是unicode编码的并且包含了urlencoded的字符。一些比赛。您可以将字符串规范化为ascci,以确保它不会被错误地解释:

>>> s = '%C3%A7%C3%B6asd+fjkls%25asd' # ascii string
>>> print urllib2.unquote(s) # works as expected
çöasd+fjkls%asd
>>> s = u'%C3%A7%C3%B6asd+fjkls%25asd' # unicode string
>>> print urllib2.unquote(s) # decode stuff that it shouldn't
çöasd+fjkls%asd
>>> print urllib2.unquote(s.encode('ascii')) # encode the unicode string to ascii: works!
çöasd+fjkls%asd

答案 5 :(得分:-1)

您正在使用unquote_plus方法考虑space并转换为+。只需使用unquote方法就可以了。

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