我有一个带有重音拉丁字符的unicode字符串,例如。
n=unicode('Wikipédia, le projet d’encyclopédie','utf-8')
我想把它转换成普通的ascii,即'Wikipedia,le projet dencyclopedie',所以所有的尖锐/重音,cedilla等应该被删除
最快的方法是什么,因为需要完成匹配长自动完成下拉列表
结论: 正如我的标准是速度,Lennart的“为unicode编码/解码注册你自己的错误处理程序”给出了最好的结果(见Alex的答案),随着越来越多的字符拉丁语,速度差异进一步增加。
这是我正在使用的转换表,也修改了错误处理程序,因为它需要处理从error.start到error.end的整个范围的未编码的char。
# -*- coding: utf-8 -*-
import codecs
"""
This is more of visual translation also avoiding multiple char translation
e.g. £ may be written as {pound}
"""
latin_dict = {
u"¡": u"!", u"¢": u"c", u"£": u"L", u"¤": u"o", u"¥": u"Y",
u"¦": u"|", u"§": u"S", u"¨": u"`", u"©": u"c", u"ª": u"a",
u"«": u"<<", u"¬": u"-", u"": u"-", u"®": u"R", u"¯": u"-",
u"°": u"o", u"±": u"+-", u"²": u"2", u"³": u"3", u"´": u"'",
u"µ": u"u", u"¶": u"P", u"·": u".", u"¸": u",", u"¹": u"1",
u"º": u"o", u"»": u">>", u"¼": u"1/4", u"½": u"1/2", u"¾": u"3/4",
u"¿": u"?", u"À": u"A", u"Á": u"A", u"Â": u"A", u"Ã": u"A",
u"Ä": u"A", u"Å": u"A", u"Æ": u"Ae", u"Ç": u"C", u"È": u"E",
u"É": u"E", u"Ê": u"E", u"Ë": u"E", u"Ì": u"I", u"Í": u"I",
u"Î": u"I", u"Ï": u"I", u"Ð": u"D", u"Ñ": u"N", u"Ò": u"O",
u"Ó": u"O", u"Ô": u"O", u"Õ": u"O", u"Ö": u"O", u"×": u"*",
u"Ø": u"O", u"Ù": u"U", u"Ú": u"U", u"Û": u"U", u"Ü": u"U",
u"Ý": u"Y", u"Þ": u"p", u"ß": u"b", u"à": u"a", u"á": u"a",
u"â": u"a", u"ã": u"a", u"ä": u"a", u"å": u"a", u"æ": u"ae",
u"ç": u"c", u"è": u"e", u"é": u"e", u"ê": u"e", u"ë": u"e",
u"ì": u"i", u"í": u"i", u"î": u"i", u"ï": u"i", u"ð": u"d",
u"ñ": u"n", u"ò": u"o", u"ó": u"o", u"ô": u"o", u"õ": u"o",
u"ö": u"o", u"÷": u"/", u"ø": u"o", u"ù": u"u", u"ú": u"u",
u"û": u"u", u"ü": u"u", u"ý": u"y", u"þ": u"p", u"ÿ": u"y",
u"’":u"'"}
def latin2ascii(error):
"""
error is protion of text from start to end, we just convert first
hence return error.start+1 instead of error.end
"""
return latin_dict[error.object[error.start]], error.start+1
codecs.register_error('latin2ascii', latin2ascii)
if __name__ == "__main__":
x = u"¼ éíñ§ÐÌëÑ » ¼ ö ® © ’"
print x
print x.encode('ascii', 'latin2ascii')
为什么我返回error.start + 1
:
返回的错误对象可以是多个字符,我们只转换其中的第一个,例如如果我将print error.start, error.end
添加到错误处理程序输出
¼ éíñ§ÐÌëÑ » ¼ ö ® © ’
0 1
2 10
3 10
4 10
5 10
6 10
7 10
8 10
9 10
11 12
13 14
15 16
17 18
19 20
21 22
1/4 einSDIeN >> 1/4 o R c '
所以在第二行我们从2-10得到字符但是我们只转换为2因此返回3作为连续点,如果我们返回error.end输出是
¼ éíñ§ÐÌëÑ » ¼ ö ® © ’
0 1
2 10
11 12
13 14
15 16
17 18
19 20
21 22
1/4 e >> 1/4 o R c '
正如我们所看到的,2-10部分已被单个字母替换。当然,只需一次编码整个范围并返回error.end就会更快,但为了演示目的,我保持简单。
有关详细信息,请参阅http://docs.python.org/library/codecs.html#codecs.register_error
答案 0 :(得分:15)
所以这里有三种方法,或多或少在其他答案中给出或建议:
# -*- coding: utf-8 -*-
import codecs
import unicodedata
x = u"Wikipédia, le projet d’encyclopédie"
xtd = {ord(u'’'): u"'", ord(u'é'): u'e', }
def asciify(error):
return xtd[ord(error.object[error.start])], error.end
codecs.register_error('asciify', asciify)
def ae():
return x.encode('ascii', 'asciify')
def ud():
return unicodedata.normalize('NFKD', x).encode('ASCII', 'ignore')
def tr():
return x.translate(xtd)
if __name__ == '__main__':
print 'or:', x
print 'ae:', ae()
print 'ud:', ud()
print 'tr:', tr()
以主要方式运行,这会发出:
or: Wikipédia, le projet d’encyclopédie
ae: Wikipedia, le projet d'encyclopedie
ud: Wikipedia, le projet dencyclopedie
tr: Wikipedia, le projet d'encyclopedie
清楚地表明基于单字母的方法虽然确实具有不需要翻译地图xtd
的便利性,但却无法以自动方式正确翻译所有字符(它适用于重音字母,但不适用于反撇号),所以它还需要一些辅助步骤来明确地处理那些(毫无疑问,现在它的身体之前)。
表演也很有趣。在我的Mac OS X 10.5和系统Python 2.5的笔记本电脑上,完全可重复:
$ python -mtimeit -s'import a' 'a.ae()'
100000 loops, best of 3: 7.5 usec per loop
$ python -mtimeit -s'import a' 'a.ud()'
100000 loops, best of 3: 3.66 usec per loop
$ python -mtimeit -s'import a' 'a.tr()'
10000 loops, best of 3: 21.4 usec per loop
translate
出乎意料地缓慢(相对于其他方法)。我认为问题在于,translate
案例中的每个字符都会查找字典(并且大部分不在那里),但仅针对那些使用asciify
方法的那些字符。
因此,为了完整性,这里采用了“加强的unicodedata”方法:
specstd = {ord(u'’'): u"'", }
def specials(error):
return specstd.get(ord(error.object[error.start]), u''), error.end
codecs.register_error('specials', specials)
def bu():
return unicodedata.normalize('NFKD', x).encode('ASCII', 'specials')
这给出了正确的输出,但是:
$ python -mtimeit -s'import a' 'a.bu()'
100000 loops, best of 3: 10.7 usec per loop
......速度不再那么好了。因此,如果速度很重要,毫无疑问,制作完整的xtd
翻译词典并使用asciify
方法是很麻烦的。当每次翻译几微秒没什么大不了的时候,人们可能只是为了方便而考虑bu
方法(只需要一个翻译字典,希望很少,特殊字符不能正确翻译底层) unicodedata idea。。
答案 1 :(得分:9)
真棒unidecode模块为您完成此任务:
>>> import unidecode
>>> n = unicode('Wikipédia, le projet d’encyclopédie','utf-8')
>>> unidecode.unidecode(n)
"Wikipedia, le projet d'encyclopedie"
答案 2 :(得分:8)
执行此操作的“正确”方法是为unicode编码/解码注册自己的错误处理程序,并在该错误处理程序中提供从è到e和ö到o等的替换。
像这样:
# -*- coding: UTF-8 -*-
import codecs
map = {u'é': u'e',
u'’': u"'",
# ETC
}
def asciify(error):
return map[error.object[error.start]], error.end
codecs.register_error('asciify', asciify)
test = u'Wikipédia, le projet d’encyclopédie'
print test.encode('ascii', 'asciify')
答案 3 :(得分:1)
Maketrans(并翻译)然后转换为ascii:
intab = u'áéí' # extend as needed
outtab = u'aei' # as well as this one
table = maketrans(intab, outtab)
text = translate(u"Wikipédia, le projet d’encyclopédie", table)
try:
temp = unicode(text, "utf-8")
fixed = unicodedata.normalize('NFKD', temp).encode('ASCII', action)
return fixed
except Exception, errorInfo:
print errorInfo
print "Unable to convert the Unicode characters to xml character entities"
raise errorInfo
(来自here)
答案 4 :(得分:0)
如果不进行测量,我希望Unicode字符串的.translate方法是最快的解决方案。不过,你一定要做自己的测量。
答案 5 :(得分:0)
Unicode文本的US-ASCII音译 一个改进版的Python unidecode,是Sean M. Burke的Text :: Unidecode Perl模块的Python端口。
pip install Unihandecode
然后在python
import unihandecode
print(unihandecode.unidecode(u'Wikipédia, le projet d’encyclopédie'))
打印Wikipedia, le projet d'encyclopedie
。