将非7位ASCII字母翻译为ASCII(如ń转n,ą转a)
我在找一种快速且方便的方法,用Python 3把包含非ASCII字母的字符串转换成只有ASCII字母的单词。
举几个例子!
żółw => zolw
móżdżek => mozdzek
łódź => lodz
等等……
很多国家的字母可以转换成ASCII字母(比如ń可以变成n)。我可以手动为我的语言(波兰语)指定每个字母的转换方式。但有没有什么自动化的方法来做到这一点?或者有没有什么库可以满足我的需求?
Python的str.encode()
方法不行,因为"żółw".encode('ascii', 'replace') == "???w"
,而"żółw".encode('ascii', 'ignore') == "w"
……
我可以为波兰字母做这样的转换,但我不想为其他语言也这样做:
>>> utf8_letters = ['ą','ę','ć','ź','ż','ó','ł','ń','ś']
>>> ascii_letters = ['a','e','c','z','z','o','l','n','s']
>>> trans_dict = dict(zip(utf8_letters,ascii_letters))
>>> turtle = "żółw"
>>> out = []
>>> for l in turtle:
... out.append(trans_dict[l] if l in trans_dict else l)
>>> result = ''.join(out)
>>> result
'zolw'
上面的代码可以处理波兰字母,但看起来太丑了 :< 有没有更好的方法?
当然,这样的转换会改变一些单词的意思,但这没关系。
1 个回答
unicodedata模块可以用来处理这个问题。它有一些函数可以操作Unicode字符的名称,比如name
和lookup
。
现在我们来仔细看看这些函数。
name('Ż') == 'LATIN CAPITAL LETTER Z WITH DOT ABOVE'
name('ł') == 'LATIN SMALL LETTER L WITH STROKE'
lookup('LATIN CAPITAL LETTER Z') == 'Z'
lookup('LATIN SMALL LETTER L') == 'l'
你发现了什么规律吗?我们来写一个利用这个规律的函数:
import unicodedata
def normalize_char(c):
try:
cname = unicodedata.name(c)
cname = cname[:cname.index(' WITH')]
return unicodedata.lookup(cname)
except (ValueError, KeyError):
return c
normalize_char('ę') == 'e'
normalize_char('Ę') == 'E'
normalize_char('ś') == 's'
这个函数会在字符名称中查找单词WITH,然后去掉它后面的所有内容,再把结果传给lookup
函数。
如果没有找到WITH,就会抛出ValueError
错误;如果没有找到对应的字符,就会抛出KeyError
错误,这样函数就会返回原来的字符。
接下来是一个基于之前函数的“翻译”字符串的函数:
def normalize(s):
return ''.join(normalize_char(c) for c in s)
normalize('Móżdżek') == 'Mozdzek'
所以这个解决方案显然是很不错的,但我会把之前的方案留在下面。
unicodedata
模块还有一个函数也能得到类似的结果——normalize
,使用'NFKD'
参数(兼容性分解),但它会漏掉大部分字符。
如果你有字符数据,你提供的代码可以进一步改进。
letters={'ł':'l', 'ą':'a', 'ń':'n', 'ć':'c', 'ó':'o', 'ę':'e', 'ś':'s', 'ź':'z', 'ż':'z'}
trans=str.maketrans(letters)
result=text.translate(trans)
这里有一个很好的字符数据表。这是JavaScript格式,但可以很容易地用于Python。
如果你不介意使用外部库,可以试试Unidecode。这个库就是为这个目的而创建的。