首页 文章

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

提问于
浏览
378

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

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

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

  • 删除Unicode类型为"diacritic"的所有字符 .

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

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

9 回答

  • 122

    回应@ 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)

  • 23

    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'
    
  • 12

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

    gensim.utils.deaccent(text)来自Gensim - topic modelling for humans

    deaccent("Šéf chomutovských komunistů dostal poštou bílý prášek") 'Sef chomutovskych komunistu dostal postou bily prasek'

    另一种解决方案是unidecode .

    并非 unicodedata 建议的解决方案通常仅在某些字符中删除重音(例如,它将 'ł' 变为 '' ,而不是 'l' ) .

  • 236

    这个怎么样:

    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'
    >>>
    

    character category "Mn"代表 Nonspacing_Mark ,类似于minQuoded中的unicodedata.combining 's answer (I didn' t想到unicodedata.combining,但它可能是更好的解决方案,因为它更明确) .

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

  • 303

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

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

  • 1

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

    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字符 .

    Edit :这就是诀窍:

    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)])
    

    如果字符 c 可以与前面的字符组合, unicodedata.combining(c) 将返回true,这主要是因为它是变音符号 .

    Edit 2remove_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)
    
  • 9
    import unicodedata
    s = 'Émission'
    search_string = ''.join((c for c in unicodedata.normalize('NFD', s) if unicodedata.category(c) != 'Mn'))
    

    对于Python 3.X

    print (search_string)
    

    对于Python 2.X

    print search_string
    
  • 6

    有些语言将变音符号作为语言字母和重音变音符号组合以指定重音 .

    我认为明确指定要剥离的diactrics是更安全的:

    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))
    

相关问题