Python如何使用十六进制字符解码unicode

Sho*_*ang 5 python utf-8 python-2.x

我已经从Web爬网脚本中提取了一个字符串,如下所示:

u'\xe3\x80\x90\xe4\xb8\xad\xe5\xad\x97\xe3\x80\x91'
Run Code Online (Sandbox Code Playgroud)

我想u'\xe3\x80\x90\xe4\xb8\xad\xe5\xad\x97\xe3\x80\x91'用utf-8 解码。使用http://ddecode.com/hexdecoder/,我可以看到结果是'????'

我尝试使用以下语法,但失败了。

msg = u'\xe3\x80\x90\xe4\xb8\xad\xe5\xad\x97\xe3\x80\x91'
result = msg.decode('utf8')
Run Code Online (Sandbox Code Playgroud)

错误:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python27\lib\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 0-11: ordi
nal not in range(128)
Run Code Online (Sandbox Code Playgroud)

请问如何正确解码字符串?

感谢帮助。

PM *_*ing 5

问题所在

msg = u'\xe3\x80\x90\xe4\xb8\xad\xe5\xad\x97\xe3\x80\x91'
result = msg.decode('utf8')
Run Code Online (Sandbox Code Playgroud)

是您正在尝试解码Unicode。那真的没有道理。您可以 Unicode 编码为某种编码类型,也可以将字节字符串解码 Unicode。

当你做

msg.decode('utf8')
Run Code Online (Sandbox Code Playgroud)

Python 2看到这msg是Unicode。它知道它无法解码Unicode,因此“有帮助”地假定您要msg使用默认的ASCII编解码器进行编码,以便可以使用UTF-8编解码器将该转换的结果解码为Unicode。Python 3的行为更加明智:代码会因以下原因而失败

AttributeError: 'str' object has no attribute 'decode'
Run Code Online (Sandbox Code Playgroud)

kennytm的答案中给出的技术:

msg.encode('latin1').decode('utf-8')
Run Code Online (Sandbox Code Playgroud)

之所以起作用,是因为小于256的Unicode代码点直接对应于Latin1编码(即ISO 8859-1)中的字符。

这是一些Python 2代码,说明了这一点:

for i in xrange(256):
    lat = chr(i)
    uni = unichr(i)
    assert lat == uni.encode('latin1')
    assert lat.decode('latin1') == uni
Run Code Online (Sandbox Code Playgroud)

这是等效的Python 3代码:

for i in range(256):
    lat = bytes([i])
    uni = chr(i)
    assert lat == uni.encode('latin1')
    assert lat.decode('latin1') == uni
Run Code Online (Sandbox Code Playgroud)

您可能会发现这篇文章很有帮助:实用Unicode,由SO老手Ned Batchelder撰写。

除非您被迫使用Python 2,否则我强烈建议您切换到Python3。这将大大简化处理Unicode的工作。