我有unicode列表
lst = [u'\xd0\xbe', u'/', u'\xd0\xb8', u'\xd1\x81', u'\xd0\xb2', u'\xd0\xba', u'\xd1\x8f', u'\xd1\x83', u'\xd0\xbd\xd0\xb0', u'____', u'|', u'\xd0\xbf\xd0\xbe', u'11', u'search', u'\xd0\xbe\xd1\x82', u'**modis**', u'15', u'\xd0\xa1', u'**avito**', u'\xd0\xbd\xd0\xb5', u'[\xd0\xa1\xd0\xbe\xd1\x85\xd1\x80\xd0\xb0\xd0\xbd\xd1\x91\xd0\xbd\xd0\xbd\xd0\xb0\xd1\x8f', u'\xd0\x92', u'\xd0\xb5\xd1\x89\xd1\x91', u'kid', u'google', u'\xd0\xbb\xd0\xb8', u'13', u'**\xd0\xb0\xd0\xb2\xd0\xb8\xd1\x82\xd0\xbe**', u'[\xd0\x9f\xd0\xbe\xd0\xba\xd0\xb0\xd0\xb7\xd0\xb0\xd1\x82\xd1\x8c', u'\xd0\x9f\xd0\xbe\xd0\xb6\xd0\xb0\xd0\xbb\xd0\xbe\xd0\xb2\xd0\xb0\xd1\x82\xd1\x8c\xd1\x81\xd1\x8f', u'\xd0\x9e', u'&parent-', u'\xd0\xaf\xd0\xbd\xd0\xb4\xd0\xb5\xd0\xba\xd1\x81', u'###', u'**avito**.', u'**kiddieland**', u'\xd0\xbc\xd0\xb0\xd0\xb3\xd0\xb0\xd0\xb7\xd0\xb8\xd0\xbd', u'45', u'click2.yandex.ru/redir', u'72']
我尝试将u'\xd0\xbe'
之类的内容转换为俄语。
我尝试使用2和3 python,但我无法做到这一点。
我使用IDE Pycharm,在设置中我有默认的utf-8。
当我用
for elem in lst:
print (elem)
它为第一个元素返回о
。当我尝试print (elem.encode('cp1252'))
时,它会返回b'\xd0\xbe'
当我使用chardet.detect
时,它返回给我,它是utf-8
。
任何人都可以向我解释,如何将其转换为俄语字母,以及为什么我使用的方法并不适合它。
答案 0 :(得分:1)
列表中的元素似乎是以UTF-8编码的字节字符串,但它们的类型为str
(或Python 2中的unicode
)。
我使用以下内容将它们转换回正确的UTF-8:
def reinterpret(string):
byte_arr = bytearray(ord(char) for char in string)
return byte_arr.decode('utf8')
这给出了以下内容,它看起来更像俄语:
>>> for elem in lst:
... print(reinterpret(elem))
...
о
/
и
с
в
к
я
у
на
____
|
по
11
search
от
**modis**
15
С
**avito**
не
[Сохранённая
В
ещё
kid
google
ли
13
**авито**
[Показать
Пожаловаться
О
&parent-
Яндекс
###
**avito**.
**kiddieland**
магазин
45
click2.yandex.ru/redir
72
答案 1 :(得分:1)
您的数据是Mojibake,从UTF-8字节错误地解码为Latin-1或CP1252。
您可以通过手动还原该过程来修复此问题:
repaired = [elem.encode('latin1').decode('utf8') for elem in lst]
但要小心;如果数据实际上被解码为cp1252,如果源数据中的0x80-0x9f范围内有任何字节,则上述情况会失败。
您可以使用ftfy
library代替;它包含可以处理强制解码的专业编解码器(其中字节被选择性地解码为Latin-1,其中缺少CP1252映射):
import ftfy
repaired = [ftfy.fix_text(elem) for elem in lst]
ftfy.fix_text()
可以很好地自动检测数据被解码的编解码器。
这两种方法都适用于您提供的样本数据;使用ftfy
或手动解码并不会对特定示例产生影响:
>>> import ftfy
>>> repaired = [ftfy.fix_text(elem) for elem in lst]
>>> repaired
[u'\u043e', u'/', u'\u0438', u'\u0441', u'\u0432', u'\u043a', u'\u044f', u'\u0443', u'\u043d\u0430', u'____', u'|', u'\u043f\u043e', u'11', u'search', u'\u043e\u0442', u'**modis**', u'15', u'\u0421', u'**avito**', u'\u043d\u0435', u'[\u0421\u043e\u0445\u0440\u0430\u043d\u0451\u043d\u043d\u0430\u044f', u'\u0412', u'\u0435\u0449\u0451', u'kid', u'google', u'\u043b\u0438', u'13', u'**\u0430\u0432\u0438\u0442\u043e**', u'[\u041f\u043e\u043a\u0430\u0437\u0430\u0442\u044c', u'\u041f\u043e\u0436\u0430\u043b\u043e\u0432\u0430\u0442\u044c\u0441\u044f', u'\u041e', u'&parent-', u'\u042f\u043d\u0434\u0435\u043a\u0441', u'###', u'**avito**.', u'**kiddieland**', u'\u043c\u0430\u0433\u0430\u0437\u0438\u043d', u'45', u'click2.yandex.ru/redir', u'72']
>>> print repaired[20]
[Сохранённая
当然,更好的解决方案是首先避免创建Mojibake。如果你能纠正错误的根源,那就更好了。
例如,如果您使用requests
库加载了此数据并假设使用response.text
属性是安全的,那么请阅读的Encodings section库文档中的高级用法章节:
请求不会执行此操作的唯一情况是,如果HTTP标头中不存在显式字符集,并且Content-Type标头包含文本。在这种情况下,RFC 2616指定默认字符集必须是ISO-8859-1。在这种情况下,请求遵循规范。如果您需要不同的编码,可以手动设置
Response.encoding
属性,或使用原始Response.content
。
因此,如果在响应中定义了字符集,response.text
将为您提供Latin-1解码文本。在这种情况下,最好避免使用response.text
并使用response.content
,并手动解码或使用格式相关的解析器来确定所使用的编解码器(例如用于HTML的BeatifulSoup)。