What is the best way to remove accents in a Python unicode string?
我在python中有一个unicode字符串,我想删除所有重音符号(音调符号)。
我在网上找到了一个在Java中实现这一点的优雅方法:
我需要安装一个库(如pyicu)还是只安装python标准库就可以做到这一点?那Python3呢?
重要提示:我希望避免使用从重音字符到非重音对应字符的显式映射的代码。
unidecode是正确的答案。它将任何Unicode字符串转换为最接近的ASCII文本表示形式。
例子:
1 2 3 4 5 | 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' |
这个怎么样?
1 2 3 4 | import unicodedata def strip_accents(s): return ''.join(c for c in unicodedata.normalize('NFD', s) if unicodedata.category(c) != 'Mn') |
这也适用于希腊字母:
1 2 3 | >>> strip_accents(u"A \u00c0 \u0394 \u038E") u'A A \u0394 \u03a5' >>> |
字符类别"mn"代表
记住,这些操作可能会显著改变文本的含义。重音符号、斜线符号等不是"装饰"。
我刚在网上找到这个答案:
1 2 3 4 5 6 | 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字符。
编辑:这就是诀窍:
1 2 3 4 5 | 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)]) |
如果字符
编辑2:
1 2 3 | 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。
多亏了你,我创造了一个神奇的功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | 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 |
结果:
1 2 | text_to_id("Montréal, über, 12.89, Mère, Fran?oise, no?l, 889") >>> 'montreal_uber_1289_mere_francoise_noel_889' |
这不仅处理重音,还处理"笔画"(如?等):
1 2 3 4 5 6 7 8 9 10 11 12 | 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(unicode(char)) cutoff = desc.find(' WITH ') if cutoff != -1: desc = desc[:cutoff] return ud.lookup(desc) |
这是我能想到的最优雅的方式(亚历克西斯在这一页的评论中提到了这一点),尽管我认为这确实不是很优雅。
还有一些特殊的字母不能用这个来处理,比如倒转字母和倒转字母,因为它们的unicode名称不包含'with'。这取决于你到底想做什么。我有时需要去除重音来实现字典的排序顺序。
对于@miniquark的回答:
我试图读取一个半法语(包含重音符号)的csv文件,以及一些最终会变成整数和浮点数的字符串。作为测试,我创建了一个
Montréal, über, 12.89, Mère, Fran?oise, no?l, 889
我必须加入行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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) |
结果:
1 2 3 4 5 6 7 | Montreal uber 12.89 Mere Francoise noel 889 |
(注意:我使用的是Mac OS X 10.8.4和Python 2.7.3)
gensim.utils.deaccent(文本)摘自gensim-人类主题建模:
'Sef chomutovskych komunistu dostal postou bily prasek'
另一个解决方案是unidecode。
不是说建议的单码数据解决方案通常只删除某些字符中的重音(例如,它将
有些语言将音调符号组合为语言字母和重音音调符号以指定重音。
我认为更安全的做法是明确说明你想去掉哪些符号:
1 2 3 4 | 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)) |