【问题标题】:Replace special characters with ASCII equivalent用等效的 ASCII 替换特殊字符
【发布时间】:2010-07-07 12:12:48
【问题描述】:

是否有任何库可以将特殊字符替换为 ASCII 等价物,例如:

"Cześć"

到:

"Czesc"

我当然可以创建地图:

{'ś':'s', 'ć': 'c'}

并使用一些替换功能。但我不想将所有等价物硬编码到我的程序中,如果有一些功能已经这样做了。

【问题讨论】:

标签: python unicode


【解决方案1】:
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import unicodedata
text = u'Cześć'
print unicodedata.normalize('NFD', text).encode('ascii', 'ignore')

【讨论】:

  • 'NFKD' 会比 'NFD' 更频繁地为您提供 ASCII 输出。
  • 它不适用于所有情况,即(VW Polo) - Zapłon Jak sprawdzić czy działa pompa wspomagania? 转换为(VW Polo) - Zapon jak sprawdzic czy dziaa pompa wspomagania?
【解决方案2】:

unidecode 包最适合我:

from unidecode import unidecode
text = "Björn, Łukasz and Σωκράτης."
print(unidecode(text))
# ==> Bjorn, Lukasz and Sokrates.

您可能需要安装该软件包:

pip install unidecode

如其他答案所建议的那样,上述解决方案比编码(和解码)unicodedata.normalize() 的输出更容易且更健壮。

# This doesn't work as expected:
ret = unicodedata.normalize('NFKD', text).encode('ascii', 'ignore')
print(ret)
# ==> b'Bjorn, ukasz and .'
# Besides not supporting all characters, the returned value is a
# bytes object in python3. To yield a str type:
ret = ret.decode("utf8") # (not required in python2)

【讨论】:

  • 它将“ß”翻译成“ss”,但将“ä”翻译成“a”,而不是“ae”。
  • @RobinDinse 这是故意的,请参阅unidecode 的文档了解其背后的原因。在将字符串传递给 unidecode 之前,您始终可以自己替换三个变音符号 äöü。
【解决方案3】:

您可以通过以下方式获得大部分的方法:

import unicodedata

def strip_accents(text):
    return ''.join(c for c in unicodedata.normalize('NFKD', text) if unicodedata.category(c) != 'Mn')

不幸的是,存在无法分解为 ASCII 字母 + 组合标记的重音拉丁字母。您必须手动处理它们。其中包括:

  • Æ → AE​​li>
  • Ð → D
  • Ø → O
  • Þ → TH
  • ß → ss
  • æ→ae
  • ð → d
  • ø → o
  • þ → 日
  • Œ → OE
  • œ → oe
  • f → f

【讨论】:

    【解决方案4】:

    试试trans 包。看起来很有前途。支持波兰语。

    【讨论】:

    • 这对我来说是完美的,而且它是 BSD 许可的。
    【解决方案5】:

    我是这样做的:

    POLISH_CHARACTERS = {
        50309:'a',50311:'c',50329:'e',50562:'l',50564:'n',50099:'o',50587:'s',50618:'z',50620:'z',
        50308:'A',50310:'C',50328:'E',50561:'L',50563:'N',50067:'O',50586:'S',50617:'Z',50619:'Z',}
    
    def encodePL(text):
        nrmtxt = unicodedata.normalize('NFC',text)
        i = 0
        ret_str = []
        while i < len(nrmtxt):
            if ord(text[i])>128: # non ASCII character
                fbyte = ord(text[i])
                sbyte = ord(text[i+1])
                lkey = (fbyte << 8) + sbyte
                ret_str.append(POLISH_CHARACTERS.get(lkey))
                i = i+1
            else: # pure ASCII character
                ret_str.append(text[i])
            i = i+1
        return ''.join(ret_str)
    

    执行时:

    encodePL(u'ąćęłńóśźż ĄĆĘŁŃÓŚŹŻ')
    

    它将产生如下输出:

    u'acelnoszz ACELNOSZZ'
    

    这对我来说很好 - ;D

    【讨论】:

      【解决方案6】:

      unicodedata.normalize 的噱头最好用 half-assci 来形容。这是一个robust approach,其中包括一张没有分解的字母图。请注意 cmets 中的其他映射条目。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-12
        • 2018-11-23
        相关资源
        最近更新 更多