我在Python中有一个Unicode字符串,我想删除所有的重音符号(变音符号).
我在Web上发现了一种在Java中执行此操作的优雅方法:
将Unicode字符串转换为长标准化形式(字母和变音符号使用单独的字符)
删除Unicode类型为"变音符号"的所有字符.
我是否需要安装pyICU等库?或者只使用python标准库?那python 3怎么样?
重要说明:我想避免代码使用重音字符到非重音符号的显式映射.
Unidecode是对此的正确答案.它将任何unicode字符串音译为ascii文本中最接近的可能表示形式.
例:
accented_string = u'Málaga' # accented_string is of type 'unicode' import unidecode unaccented_string = unidecode.unidecode(accented_string) # unaccented_string contains 'Malaga'and is of type 'str'
这个怎么样:
import unicodedata def strip_accents(s): return ''.join(c for c in unicodedata.normalize('NFD', s) if unicodedata.category(c) != 'Mn')
这也适用于希腊字母:
>>> strip_accents(u"A \u00c0 \u0394 \u038E") u'A A \u0394 \u03a5' >>>
该字符类别 "锰"表示Nonspacing_Mark
,这是类似于MiniQuark的答案unicodedata.combining(我没想到unicodedata.combining的,但它可能是更好的解决方案,因为它更明确).
请记住,这些操作可能会显着改变文本的含义.口音,变音等不是"装饰".
我刚刚在网上找到了这个答案:
import unicodedata def remove_accents(input_str): nfkd_form = unicodedata.normalize('NFKD', input_str) only_ascii = nfkd_form.encode('ASCII', 'ignore') return only_ascii
它运行正常(例如法语),但我认为第二步(删除重音符号)可以比删除非ASCII字符更好地处理,因为对于某些语言(例如希腊语)会失败.最好的解决方案可能是明确删除被标记为变音符号的unicode字符.
编辑:这样做的诀窍:
import unicodedata def remove_accents(input_str): nfkd_form = unicodedata.normalize('NFKD', input_str) return u"".join([c for c in nfkd_form if not unicodedata.combining(c)])
unicodedata.combining(c)
如果角色c
可以与前面的角色组合,则返回true ,主要是因为它是变音符号.
编辑2:remove_accents
需要一个unicode字符串,而不是一个字节字符串.如果你有一个字节字符串,那么你必须将它解码为一个unicode字符串,如下所示:
encoding = "utf-8" # or iso-8859-15, or cp1252, or whatever encoding you use byte_string = b"café" # or simply "café" before python 3. unicode_string = byte_string.decode(encoding)
实际上我在项目兼容的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'
这不仅可以处理重音,还可以处理"笔画"(如ø等):
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名称不包含'WITH'.这取决于你想要做什么.我有时需要重音剥离来实现字典排序顺序.
回应@ MiniQuark的回答:
我试图读取一个半法语(包含重音符号)的csv文件以及一些最终会变成整数和浮点数的字符串.作为测试,我创建了一个如下所示的test.txt
文件:
蒙特利尔,über,12.89,Mère,Françoise,noël,889
我必须包含行2
并3
使其工作(我在python票证中找到),以及合并@ Jabba的评论:
import sys reload(sys) sys.setdefaultencoding("utf-8") import csv import unicodedata def remove_accents(input_str): nkfd_form = unicodedata.normalize('NFKD', unicode(input_str)) return u"".join([c for c in nkfd_form if not unicodedata.combining(c)]) with open('test.txt') as f: read = csv.reader(f) for row in read: for element in row: print remove_accents(element)
结果:
Montreal uber 12.89 Mere Francoise noel 889
(注意:我使用的是Mac OS X 10.8.4并使用Python 2.7.3)
来自Gensim的gensim.utils.deaccent(text)- 人类主题建模:
'?'
另一个解决方案是unidecode.
不与该建议的解决方案unicodedata通常仅在一些字符消除重音符号(例如,它变成''
入'l'
,而不是进入'?'
).