如何在Python中将HTML非ASCII数据编码为UTF-8

时间:2010-03-07 16:15:17

标签: python unicode utf-8

我试图这样做,我发现了这个错误:

>>> import re  
>>> x = 'Ingl\xeas'  
>>> x  
'Ingl\xeas'  
>>> print x  
Ingl�s  
>>> x.decode('utf8')  
Traceback (most recent call last):  
    File "<stdin>", line 1, in <module>  
    File "/usr/lib/python2.6/encodings/utf_8.py", line 16, in decode  
        return codecs.utf_8_decode(input, errors, True)  
UnicodeDecodeError: 'utf8' codec can't decode bytes in position 4-5: unexpected end of data  
>>> x.decode('utf8', 'ignore')  
u'Ingl'  
>>> x.decode('utf8', 'replace')  
u'Ingl\ufffd'  
>>> print x.decode('utf8', 'replace')  
Ingl�  
>>> print x.decode('utf8', 'xmlcharrefreplace')  
Traceback (most recent call last):  
    File "<stdin>", line 1, in <module>  
    File "/usr/lib/python2.6/encodings/utf_8.py", line 16, in decode  
        return codecs.utf_8_decode(input, errors, True)  
TypeError: don't know how to handle UnicodeDecodeError in error callback  

当我使用print语句时,我想要:

>>> print x  
u'Inglês'  

欢迎任何帮助。

3 个答案:

答案 0 :(得分:7)

在解码之前,您需要知道输入数据的编码方式。在你们的一些尝试中,你试图从UTF-8解码它,但是Python抛出一个异常,因为输入是无效的UTF-8。看起来它可能是拉丁语-1。这对我有用:

>>> x = 'Ingl\xeas'
>>> print x.decode('latin1')
Inglês

你提到“非ASCII HTML”。如果您正在编写Web服务器脚本并且从HTTP请求获取数据,则应检查Content-Type标头。在理想的世界中,它会告诉您客户端使用哪种编码方式来处理数据。请记住,客户端可能无法正常工作。

希望有所帮助!

答案 1 :(得分:0)

Ingl\xeas

不是UTF-8,而是(可能)Windows-1252-或latin1编码。所以你首先需要解码它。只有这样你才能将它编码为UTF-8。

因此:

>>> x = 'Ingl\xeas'
>>> print x.decode("cp1252")
Inglês

类似地,

 >>> x.decode("cp1252").encode("UTF-8")
 'Ingl\xc3\xaas'

这是正确的UTF-8表示。

顺便说一句,在Python 3中,你可以(至少在Windows下的交互式控制台中)输入

>>> x = 'Ingl\xeas'
>>> print (x)
Inglês

因为Python 3字符串总是Unicode字符串(不包括bytes个对象)。

答案 2 :(得分:0)

一些观察结果:

(1)latin1将解码任何8位字节而不抛出异常。仅在您用尽所有其他可能性时才使用latin1。使用chardet帮助确定特定文件或网页或XML流的编码内容。

(2)基于非常有限的证据(一个字符)的可能替代方案:

>>> import unicodedata as ucd
>>> for codepage in range(1250, 1259):
...    try:
...        uc = "\xea".decode(str(codepage))
...    except UnicodeDecodeError:
...        pass
...    if uc == u'\xea': print codepage, ucd.name(uc)
...
1252 LATIN SMALL LETTER E WITH CIRCUMFLEX
1254 LATIN SMALL LETTER E WITH CIRCUMFLEX
1256 LATIN SMALL LETTER E WITH CIRCUMFLEX
1258 LATIN SMALL LETTER E WITH CIRCUMFLEX
>>>

(3)范围U + 0080到U + 009F(包括)被分配给“C1控制字符”,unicode.org之外没有人知道它们可能有什么用途。无论你使用什么编码(甚至是UTF-8),在无异常解码到unicode之后,你还没有走出困境。检查该范围内的字符。如果您发现任何数据,您的数据已损坏,或者您选择的编码不正确。

def check_for_c1_control_characters(unicode_obj):
    return any('\u0080' <= c <= '\u009F' for c in unicode_obj)

或使用正则表达式,如this example中所述,如何修复数据损坏的多种方式之一。