Answers:
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'
unidecode
替换°
为deg
。它所做的不仅仅是删除重音符号。
这个怎么样:
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的,但它可能是更好的解决方案,因为它更明确)。
请记住,这些操作可能会大大改变文本的含义。口音,Umlauts等不是“装饰”。
unicodedata.name
分解并使用相似的表格-无论如何,您都需要希腊字母(A只是“希腊大写字母ALPHA”)。
A
。如果不希望,请不要这样做,但是在两种情况下,您都将替换拉丁字母(近似)。
ß
为ascii ss
。我仍然会使用unidecode
以避免事故。
我刚刚在网上找到了这个答案:
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)
nkfd_form = unicodedata.normalize('NFKD', unicode(input_str, 'utf8'))
, 'utf8'
如果要在终端中测试输入(默认情况下不使用unicode),则是一个“安全网”。但通常你不会有加它,因为如果你删除的口音那么input_str
很可能是UTF8了。不过,安全不会有什么坏处。
remove_accents
而不是常规字符串(u“é”而不是“é”)。您将常规字符串传递给remove_accents
,因此在尝试将字符串转换为unicode字符串时,使用了默认ascii
编码。此编码不支持任何值大于127的字节。在外壳程序中键入“é”时,您的操作系统可能使用UTF-8或某些Windows代码页编码对其进行了编码,并且包含的字节数> 127。我将更改函数以删除对Unicode的转换:如果传递了非Unicode字符串,它将更加清晰地轰炸。
实际上,我正在开发与项目兼容的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'
text = unicode(text, 'utf-8')
。为此添加了一种解决方法except TypeError: pass
这不仅处理重音,而且还处理“笔画”(如ø等):
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
这是我能想到的最优雅的方式(alexis在此页的评论中已经提到),尽管我认为这确实不是很优雅。实际上,正如注释中所指出的那样,这更像是一种黑客,因为Unicode名称是–实际上只是名称,它们不能保证其一致性或任何形式。
由于它们的Unicode名称中不包含“ WITH”,因此仍有一些特殊的字母无法对此进行处理,例如转弯和倒转字母。无论如何,这取决于您想做什么。有时我需要重音符号来实现字典的排序顺序。
合并了注释中的建议(处理查找错误,Python-3代码)。
unicode
在其中使用python 3 进行函数调用?我认为使用更严格的正则表达式find
可以避免上面评论中提到的所有麻烦,而且,当它是关键代码路径时,备忘录可以帮助提高性能。
unicode
类型转换是在Python 3不再适合在任何情况下,在我的经验有没有普遍的,优雅的解决了这个问题。根据应用程序的不同,任何方法都有其优缺点。诸如质量提升工具等unidecode
都是基于手工制作的表格。某些资源(表,算法)由Unicode提供,例如。进行排序。
回应@MiniQuark的回答:
我试图读取一个半法语的csv文件(包含重音符号)以及一些最终会变成整数和浮点数的字符串。作为测试,我创建了一个如下所示的test.txt
文件:
蒙特利尔,于伯,12.89,梅尔,弗朗索瓦,诺尔,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)
remove_accents
旨在从Unicode字符串中删除重音符号。如果它传递了字节字符串,它将尝试使用将其转换为unicode字符串unicode(input_str)
。这使用python的默认编码,即“ ascii”。由于您的文件使用UTF-8编码,因此将失败。第2行和第3行将python的默认编码更改为UTF-8,因此如您所知,它可以正常工作。另一种选择是传递remove_accents
unicode字符串:删除第2行和第3行,最后一行替换element
为element.decode("utf-8")
。我测试了:可以。我将更新答案以使其更清楚。
iso-8859-1
,很遗憾,我无法使用此功能!)
reload(sys); sys.setdefaultencoding("utf-8")
是一种可疑的黑客工具,有时建议用于Windows系统。有关详细信息,请参见stackoverflow.com/questions/28657010/…。
gensim.utils.deaccent(文本)从Gensim -人类主题建模:
'Sef chomutovskych komunistu dostal postou bily prasek'
另一个解决方案是unidecode。
需要注意的是,用建议的解决方案unicodedata通常只在某些字符去掉口音(例如,它变成'ł'
成''
,而不是进入'l'
)。
deaccent
仍然给予ł
而不是l
。
NumPy
并SciPy
得到去除口音。
一些语言结合了变音符号作为语言字母和重音符号来指定重音。
我认为更明确地指定要去除的折光度数更安全:
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))