私はPythonのUnicode文字列を持っています、そして私はすべてのアクセント(発音区別符号)を取り除きたいです。
私はWeb上でこれをJavaで実行するためのエレガントな方法を見つけました。
PyICUなどのライブラリをインストールする必要がありますか、それともpython標準ライブラリだけで可能ですか?そして、Python 3はどうですか?
重要な注意:アクセント記号付きの文字からアクセント記号なしの対応する部分への明示的なマッピングを伴うコードは避けたいと思います。
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'
これはどう:
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は考えていませんでしたが、それはより明確なので、おそらくそれはより良い解決策です。
そして、覚えておいてください、これらの操作はテキストの意味を著しく変えるかもしれません。アクセント、ウムラウトなどは「装飾」ではありません。
私はちょうど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)])
文字c
が直前の文字と結合できる場合、つまり主に発音区別符号である場合、unicodedata.combining(c)
はtrueを返します。
編集2:remove_accents
はバイト文字列ではなくユニコード文字列を期待します。バイト文字列がある場合は、それを次のような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)
実際、私はプロジェクト互換の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'
これはアクセントだけでなく "ストローク"も扱います(øなど)。
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)
これは私が考えることができる最もエレガントな方法です(そしてそれはこのページのコメントでalexisによって言及されました)、私はそれが本当にとてもエレガントだとは思いませんが。
ユニコード名には 'WITH'が含まれていないため、これまでに処理されていない特殊な文字(回転文字や反転文字など)がまだあります。とにかくやりたいことによります。辞書のソート順を達成するためにアクセントの削除が必要になることがありました。
@ MiniQuarkの回答に答えて:
私は(アクセントを含む)半フランス語のcsvファイルを読み込もうとしていましたが、最終的に整数や浮動小数点数になることもありました。テストとして、私は次のような外観のtest.txt
ファイルを作成しました。
モントリオール、über、12.89、その他、Françoise、noël、889
私はそれを動かすために2
と3
の行を含めなければなりません(私は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を使用しています)
gensim.utils.deaccent(text) から Gensim - トピックモデリングのための人間 :
deaccent("Šéf chomutovských komunistů dostal poštou bílý prášek") 'Sef chomutovskych komunistu dostal postou bily prasek'
別の解決策は unidecode です。
unicodedataを使用して提案された解決策は、通常、ある文字のみでアクセントを削除します(たとえば、'ł'
ではなく''
を'l'
に変換します)。
一部の言語では、アクセント記号を指定するために、言語文字としての発音区別符号とアクセント記号の発音区別符号の組み合わせがあります。
どの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))