为什么规范化会将未定义的字符更改为“a”?

时间:2017-02-16 15:47:58

标签: python python-3.x

我正在尝试编写一个脚本,用于规范化存储在我的MP3文件中的艺术家名称。我遇到的问题是引用here的unicodedata.normalize函数将大多数重音字符转换为'a'。这是代码和输出

def remove_accents(data):
return ''.join(x for x in unicodedata.normalize('NFD', data) if x in string.ascii_letters).lower()

string2 = "Mötley Crüe"

string3 = makeEnglish3.convertChars(string2)
print(string3)

输出

matleycrae

我希望杂乱无章,我做错了什么?

1 个答案:

答案 0 :(得分:2)

看看打印此latin1字符串时会发生什么。

# -- coding: latin-1 --
string2 = "Mötley Crüe"
print(string2)

它打印Mötley Crüe。请注意,Ã之后的字符是不是字母。在以下代码段中,该代码段实际上是您的remove_accents()函数,它将去除非字母字符:

import unicodedata
for x in unicodedata.normalize('NFD', string2):
    if x in string.ascii_letters:
       print(x, end='')

输出MAtleyCrAe。即使使用带有诸如shåpÈ之类的不同组合字符的字符串,仍会打印为shÃ¥pÃ,因为即使保存了文件,您的python文件中的字节序列也被解释为latin1 在文件系统中为UTF-8。

为什么字符被读为'Ã'?

让我们检查这些字符的字节组成:

>>> bytes('ö', 'utf-8')
b'\xc3\xb6'
>>> bytes('ü', 'utf-8')
b'\xc3\xbc'
>>> bytes('ö', 'utf-8').decode('latin1')
'ö'
>>> bytes('ü', 'utf-8').decode('latin1')
'ü'

您会看到这些带重音的字符表示为\xc3,后跟其他十六进制数字。在拉丁语1中,\xc3是Ã。由于其他字符也可能会转换为字母,因此您可能还会看到Ã后跟一个随机字母。这就是输出中的“ a”(在删除重音并将其变为小写之后)的原因。