650

Python に Unicode 文字列があり、すべてのアクセント (分音記号) を削除したいと考えています。

これを行うためのエレガントな方法をWebで見つけました(Javaで):

  1. Unicode 文字列を正規化された長い形式に変換します(文字と分音記号は別の文字で)
  2. Unicode タイプが「diacritic」であるすべての文字を削除します。

pyICU などのライブラリをインストールする必要がありますか、それとも Python 標準ライブラリだけで可能ですか? そしてpython 3はどうですか?

重要な注意: アクセント付きの文字からアクセントのない対応する文字への明示的なマッピングを含むコードは避けたいと思います。

4

11 に答える 11

638

これに対する正解は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'
于 2010-04-13T21:21:14.497 に答える
344

これはどう:

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

文字カテゴリ「Mn」は を表しNonspacing_Mark、これは MiniQuark の回答の unicodedata.combining に似ています (unicodedata.combining については考えていませんでしたが、より明示的であるため、おそらくより良い解決策です)。

これらの操作は、テキストの意味を大幅に変更する可能性があることに注意してください。アクセント、ウムラウトなどは「装飾」ではありません。

于 2009-02-05T22:17:22.780 に答える
182

Webでこの回答を見つけました:

import unicodedata

def remove_accents(input_str):
    nfkd_form = unicodedata.normalize('NFKD', input_str)
    only_ascii = nfkd_form.encode('ASCII', 'ignore')
    return only_ascii

これは問題なく動作しますが (たとえば、フランス語の場合)、2 番目のステップ (アクセントの削除) は、一部の言語 (たとえばギリシャ語) では失敗するため、非 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_accentsUnicode文字列が必要です。バイト文字列がある場合は、次のように 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)
于 2009-02-05T21:19:34.470 に答える
29

これは、アクセントだけでなく、「ストローク」(ø など) も処理します。

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

これは私が考えることができる最もエレガントな方法です (このページのコメントで alexis によって言及されています) が、実際には非常にエレガントだとは思いません。実際、コメントで指摘されているように、Unicode 名は単なる名前であり、一貫性などを保証するものではないため、これはハックのようなものです。

Unicode 名に 'WITH' が含まれていないため、回転文字や反転文字など、これで処理されない特殊文字がまだあります。とにかく何をしたいかによります。辞書の並べ替え順序を実現するために、アクセントの除去が必要になることがありました。

編集注:

コメントからの提案を組み込みました (検索エラーの処理、Python-3 コード)。

于 2013-03-21T12:39:18.177 に答える
4

一部の言語では、言語文字としての分音記号と、アクセントを指定するためのアクセント分音記号を組み合わせています。

取り除きたいダイアトリックを明示的に指定する方が安全だと思います:

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))
于 2015-07-24T11:34:02.997 に答える