在Python 2.7中使用unicodedata.normalize

dpi*_*h40 7 python unicode normalization unicode-normalization python-2.7

再一次,我对unicode问题非常困惑.我无法弄清楚如何成功使用unicodedata.normalize按预期转换非ASCII字符.例如,我想转换字符串

u"Cœur"
Run Code Online (Sandbox Code Playgroud)

u"Coeur"
Run Code Online (Sandbox Code Playgroud)

我很确定unicodedata.normalize是这样做的方法,但我不能让它工作.它只是保持字符串不变.

>>> s = u"Cœur"
>>> unicodedata.normalize('NFKD', s) == s
True
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?

jfs*_*jfs 20

你可以尝试Unidecode:

# -*- coding: utf-8 -*-
from unidecode import unidecode # $ pip install unidecode

print(unidecode(u"Cœur"))
# -> Coeur
Run Code Online (Sandbox Code Playgroud)


jsb*_*eno 6

你的问题似乎与Python没有关系,但是你试图分解的角色(u'\ u0153' - 'œ')本身并不是一个组合.

检查您的代码是否使用包含正常复合字符(如"ç"和"ã")的字符串:

>>> a1 = a
>>> a = u"maçã"
>>> for norm in ('NFC', 'NFKC', 'NFD','NFKD'):
...    b = unicodedata.normalize(norm, a)
...    print b, len(b)
... 
maçã 4
maçã 4
maçã 6
maçã 6
Run Code Online (Sandbox Code Playgroud)

然后,如果你检查两个字符(你的和c + cedila)的unicode引用,你会看到后者有一个前面缺乏的"分解"规范:

http://www.fileformat.info/info/unicode/char/153/index.htm
http://www.fileformat.info/info/unicode/char/00e7/index.htm

它就像"œ"在形式上并不等同于"oe" - (至少不适用于定义此unicode部分的人) - 因此,规范化包含此文本的文本的方法是手动替换字符为序列与unicode.replace - 听起来像hacky.