那么让我们从您的测试输入开始:
In [1]: test
Out[1]: 'ewaláièÜÖ'
看看在规范化时它发生了什么:
In [2]: [x for x in unicodedata.normalize('NFD', test)]
Out[2]: ['e', 'w', 'a', 'l', 'a', '́', 'i', 'e', '̀', 'U', '̈', 'O', '̈']
以下是每个规范化元素的unicode数据类别:
In [3]: [unicodedata.category(x) for x in unicodedata.normalize('NFD', test)]
Out[3]: ['Ll', 'Ll', 'Ll', 'Ll', 'Ll', 'Mn', 'Ll', 'Ll', 'Mn', 'Lu', 'Mn', 'Lu', 'Mn']
正如您所看到的,不仅“accents”,而且“umlauts”都属于类别Mn
。因此,您可以使用 unicodedata.name
替代 unicodedata.category
In [4]: [unicodedata.name(x) for x in unicodedata.normalize('NFD', test)]
Out[4]: ['LATIN SMALL LETTER E',
'LATIN SMALL LETTER W',
'LATIN SMALL LETTER A',
'LATIN SMALL LETTER L',
'LATIN SMALL LETTER A',
'COMBINING ACUTE ACCENT',
'LATIN SMALL LETTER I',
'LATIN SMALL LETTER E',
'COMBINING GRAVE ACCENT',
'LATIN CAPITAL LETTER U',
'COMBINING DIAERESIS',
'LATIN CAPITAL LETTER O',
'COMBINING DIAERESIS']
这里的重音名称是
COMBINING ACUTE/GRAVE ACCENT
,而"umlauts"名称是
COMBINING DIAERESIS
。因此,这是我的建议,如何修复你的代码:
def strip_accents(s):
return ''.join(c for c in unicodedata.normalize('NFD', s)
if not unicodedata.name(c).endswith('ACCENT'))
strip_accents(test)
'ewalaieÜÖ'
同时,正如你可以从unicodedata文档中了解到的那样,这个模块只是一个包装器,用于数据库可在这里找到,因此请查看来自该数据库的名称列表以确保它涵盖了您需要的所有情况。
Normalizer.normalize(s, Normalizer.Form.NFKD).replaceAll("((?<![aouAOU])\\p{M})|((?<=[aouAOU])[\\p{M}&&[^\u0308]])", "")
。首先,将Unicode规范化为分解形式,以将次要字符(如重音符号)与主要字符(如"a")分离开来。然后,我们删除所有未在[aouAOU]之前的次要字符,以及除\u0308(组合分音符)之外的所有次要字符。可以使用Normalizer.normalize(s, Normalizer.Form.NFKC)
重新组合结果。 - user27772