我在Python中有一个Unicode字符串,我想删除所有的重音(变音符)。
我在网上找到了一个优雅的方法(在Java中):
将Unicode字符串转换为它的长规范化形式(使用单独的字符表示字母和变音符) 删除所有Unicode类型为“变音符”的字符。
我需要安装一个库,如pyICU或这是可能的Python标准库?那么python3呢?
重要提示:我希望避免使用从重音字符到非重音对应字符的显式映射的代码。
我在Python中有一个Unicode字符串,我想删除所有的重音(变音符)。
我在网上找到了一个优雅的方法(在Java中):
将Unicode字符串转换为它的长规范化形式(使用单独的字符表示字母和变音符) 删除所有Unicode类型为“变音符”的字符。
我需要安装一个库,如pyICU或这是可能的Python标准库?那么python3呢?
重要提示:我希望避免使用从重音字符到非重音对应字符的显式映射的代码。
当前回答
这不仅可以处理重音,还可以处理“笔画”(如ø等):
import unicodedata as ud
def rmdiacritics(char):
'''
Return the base character of char, by "removing" any
diacritics like accents or curls and strokes and the like.
'''
desc = ud.name(char)
cutoff = desc.find(' WITH ')
if cutoff != -1:
desc = desc[:cutoff]
try:
char = ud.lookup(desc)
except KeyError:
pass # removing "WITH ..." produced an invalid name
return char
这是我能想到的最优雅的方式(亚历克西斯在本页的评论中提到过),尽管我不认为它真的很优雅。 事实上,正如评论中指出的那样,这更像是一种黑客,因为Unicode名称实际上只是名称,它们不能保证一致或任何东西。
仍然有一些特殊的字母没有被处理,比如反转字母和倒装字母,因为它们的unicode名称不包含'WITH'。这取决于你想做什么。我有时需要重音剥离来实现字典排序顺序。
编辑注:
合并了来自注释的建议(处理查找错误,Python-3代码)。
其他回答
unidcode是正确的答案。它将任何unicode字符串音译为最接近的ascii文本表示形式。
例子:
>>> from unidecode import unidecode
>>> unidecode('kožušček')
'kozuscek'
>>> unidecode('北亰')
'Bei Jing '
>>> unidecode('François')
'Francois'
实际上,我在项目兼容的python 2.6, 2.7和3.4上工作,我必须从免费用户条目中创建id。
感谢你,我创造了这个功能,工作的奇迹。
import re
import unicodedata
def strip_accents(text):
"""
Strip accents from input String.
:param text: The input string.
:type text: String.
:returns: The processed String.
:rtype: String.
"""
try:
text = unicode(text, 'utf-8')
except (TypeError, NameError): # unicode is a default on python 3
pass
text = unicodedata.normalize('NFD', text)
text = text.encode('ascii', 'ignore')
text = text.decode("utf-8")
return str(text)
def text_to_id(text):
"""
Convert input text to id.
:param text: The input string.
:type text: String.
:returns: The processed String.
:rtype: String.
"""
text = strip_accents(text.lower())
text = re.sub('[ ]+', '_', text)
text = re.sub('[^0-9a-zA-Z_-]', '', text)
return text
结果:
text_to_id("Montréal, über, 12.89, Mère, Françoise, noël, 889")
>>> 'montreal_uber_1289_mere_francoise_noel_889'
在我看来,所提出的解决办法不应该是公认的答案。原来的问题是要求去掉重音,所以正确的答案应该只去掉重音,而不是去掉重音加上其他未指明的变化。
简单地观察这段代码的结果,这是公认的答案。我把“Málaga”改成了“Málagueña”:
accented_string = u'Málagueña'
# accented_string is of type 'unicode'
import unidecode
unaccented_string = unidecode.unidecode(accented_string)
# unaccented_string contains 'Malaguena'and is of type 'str'
有一个额外的更改(ñ -> n),这在OQ中没有请求。
一个简单的函数,以较低的形式完成所请求的任务:
def f_remove_accents(old):
"""
Removes common accent characters, lower form.
Uses: regex.
"""
new = old.lower()
new = re.sub(r'[àáâãäå]', 'a', new)
new = re.sub(r'[èéêë]', 'e', new)
new = re.sub(r'[ìíîï]', 'i', new)
new = re.sub(r'[òóôõö]', 'o', new)
new = re.sub(r'[ùúûü]', 'u', new)
return new
如果您希望获得类似Elasticsearch的ascii折叠过滤器的功能,您可能需要考虑fold-to-ascii,这是[本身]…
Apache Lucene ASCII折叠过滤器的Python端口,它将字母、数字和符号Unicode字符转换为不属于前127个ASCII字符的字符(“基本拉丁”Unicode块),如果它们存在的话。
下面是上面提到的一个例子:
from fold_to_ascii import fold
s = u'Astroturf® paté'
fold(s)
> u'Astroturf pate'
fold(s, u'?')
> u'Astroturf? pate'
编辑:fold_to_ascii模块似乎可以很好地规范化基于拉丁的字母;然而,不可映射的字符将被删除,这意味着该模块将减少中文文本,例如,空字符串。如果您想保留中文、日语和其他Unicode字母,可以考虑使用上面@mo-han的remove_accent_chars_regex实现。
有些语言将变音符组合成语言字母,并将重音变音符组合成重音。
我认为更安全的做法是明确指定你想要剥离的变量:
def strip_accents(string, accents=('COMBINING ACUTE ACCENT', 'COMBINING GRAVE ACCENT', 'COMBINING TILDE')):
accents = set(map(unicodedata.lookup, accents))
chars = [c for c in unicodedata.normalize('NFD', string) if c not in accents]
return unicodedata.normalize('NFC', ''.join(chars))