当前位置:  开发笔记 > 编程语言 > 正文

删除Python unicode字符串中重音的最佳方法是什么?

如何解决《删除Pythonunicode字符串中重音的最佳方法是什么?》经验,为你挑选了7个好方法。

我在Python中有一个Unicode字符串,我想删除所有的重音符号(变音符号).

我在Web上发现了一种在Java中执行此操作的优雅方法:

    将Unicode字符串转换为长标准化形式(字母和变音符号使用单独的字符)

    删除Unicode类型为"变音符号"的所有字符.

我是否需要安装pyICU等库?或者只使用python标准库?那python 3怎么样?

重要说明:我想避免代码使用重音字符到非重音符号的显式映射.



1> Christian Ou..:

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'


似乎与中国人合作很好,但不幸的是,法国名字"弗朗索瓦"的转变给了"FranASSois",与更自然的"弗朗索瓦"相比,它不是很好.
@EOL unidecode适用于像"François"这样的字符串,如果你将unicode对象传递给它.看起来你尝试使用普通字节字符串.
请注意,unidecode> = 0.04.10(2012年12月)是GPL.如果您需要更宽松的许可证,请使用早期版本或检查https://github.com/kmike/text-unidecode,并且可以使用稍差的实施.
取决于你想要实现的目标.例如我现在正在搜索,我不想音译希腊语/俄语/中文,我只想用"a/e/s/c"替换"ą/ę/ś/ć"
`unidecode`用'deg`替换`°`.它不仅仅是删除重音.
人们需要理解Unicode字符分解是一种特定于语言的映射,它不能普遍使用,而像unidecode这样的模块在忽略输入的语言环境或语言时永远不会正常工作.至于CJK字符,这是一个幼稚的假设,你可以采用任意CJK字符并用ASCII"渲染"它:CJK字符可以有多个中文和日文读数,中文,日文等读数也是与众不同.这些模块浪费时间.
@chhantyalÖ=> OE非常具有德国特色.在芬兰语中,像"ääliö"这样的词会使完全无法辨认的"aeaelioe"; 省略diaresis比添加'e`更为正确,尽管重音字母的发音几乎与德国变音符号相同.
似乎不适用于德国,例如.Ö=> O应该是大江

2> oefe..:

这个怎么样:

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的,但它可能是更好的解决方案,因为它更明确).

请记住,这些操作可能会显着改变文本的含义.口音,变音等不是"装饰".


不幸的是,这些不是由角色组成的 - 尽管"ł"被命名为"LATIN SMALL LETTER L WITH STROKE"!你要么需要解析`unicodedata.name`来玩游戏,要么分解并使用一个相似的表 - 无论如何你都需要希腊字母(Α只是"GREEK CAPITAL LETTER ALPHA").
@alexis(后期跟进):这对于希腊语也非常适用-例如。正如预期的那样,“带有大亚和VARIA的希腊字母大写字母”被标准化为“希腊字母大写字母”。除非您指的是*音译*(例如“α”→“ a”),否则与“去除口音”不同...

3> MiniQuark..:

我刚刚在网上找到了这个答案:

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)


我不得不在unicode中添加'utf8':`nkfd_form = unicodedata.normalize('NFKD',unicode(input_str,'utf8'))`

4> hexaJer..:

实际上我在项目兼容的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'


使用Py2.7,在`text = unicode(text,'utf-8')`传递已经是unicode的字符串错误.解决方法是添加`fromTypeError:pass`

5> lenz..:

这不仅可以处理重音,还可以处理"笔画"(如ø等):

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'.这取决于你想要做什么.我有时需要重音剥离来实现字典排序顺序.


如果新符号不存在,您应该捕获异常.例如,有SQUARE WITH VERTICAL FILL▥,但没有SQUARE.(更不用说这个代码将UMBRELLA与RAIN DROPS trans一起转换为UMBRELLA☂).

6> aseagram..:

回应@ MiniQuark的回答:

我试图读取一个半法语(包含重音符号)的csv文件以及一些最终会变成整数和浮点数的字符串.作为测试,我创建了一个如下所示的test.txt文件:

蒙特利尔,über,12.89,Mère,Françoise,noël,889

我必须包含行23使其工作(我在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)



7> Piotr Migdal..:

来自Gensim的gensim.utils.deaccent(text)- 人类主题建模:

'?'

另一个解决方案是unidecode.

不与该建议的解决方案unicodedata通常仅在一些字符消除重音符号(例如,它变成'''l',而不是进入'?').

推荐阅读
360691894_8a5c48
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有