Что является лучшим способом, чтобы удалить акценты в строку Python Юникод?
У меня есть строка Unicode в Python, и я хотел бы удалить все акценты (диакритические знаки).
Я нашел в Интернете элегантный способ сделать это в Java:
- преобразуйте строку Юникода в ее длинную нормализованную форму (с отдельным символом для букв и диакритических знаков)
- удалите все символы, тип Юникода которых является "диакритическим".
Мне нужно установить библиотеку, такую как pyICU, или это возможно только с помощью python стандартная библиотека? А как насчет python 3?
важное примечание: Я хотел бы избежать кода с явным отображением от акцентированных символов к их не акцентированному аналогу.
9 ответов:
Unidecode - это правильный ответ для этого. Он транслитерирует любую строку юникода в самое близкое возможное представление в тексте 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' >>>The категория символов "Mn" означает
Nonspacing_Mark, который похож на unicodedata.объединение в ответе MiniQuark (я не думал о unicodedata.комбинирование, но это, вероятно, лучшее решение, потому что оно более явное).и имейте в виду, что эти манипуляции могут существенно изменить смысл текста. Акценты, умлауты и др. не "украшение."
Я только что нашел этот ответ в Интернете:
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, потому что это не удастся для некоторых языков (греческий, например). Лучшим решением, вероятно, было бы явное удаление символов Юникода, которые помечены как диакритические знаки.
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)])
unicodedata.combining(c)возвращает true, если символcможет быть объединен с предыдущим символом, то есть в основном, если это диакритический.Edit 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)
На самом деле я работаю над совместимым с проектом python 2.6, 2.7 и 3.4, и мне нужно создавать идентификаторы из бесплатных записей пользователей.
благодаря вам, я создал эту функцию, которая творит чудеса.
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)есть еще специальные буквы, которые не обрабатываются этим, например, перевернутые и перевернутые буквы, так как их имя unicode не содержит "с". Это зависит от того, что вы хотите сделать в любом случае. Мне иногда нужен был акцент зачистка для достижения порядка сортировки словаря.
в ответ на ответ @MiniQuark:
Я пытался читать в csv-файле, который был наполовину французским (содержащим акценты), а также некоторые строки, которые в конечном итоге станут целыми числами и плавающими. В качестве теста, я создал
test.txtфайл, который выглядел так:Монреаль, Убер, 12.89, Mère, 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)
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
gensim.utils.deaccent(текст) С Gensim-тема моделирования для людей:
deaccent("Šéf chomutovských komunistů dostal poštou bílý prášek") 'Sef chomutovskych komunistu dostal postou bily prasek'другое решение -unidecode.
не то, что предлагаемое решение с unicodedata обычно удаляет акценты только в некоторых символах (например, он поворачивается
'ł'на'', а не'l').
некоторые языки объединяют диакритические знаки как буквы языка и диакритические знаки акцента для указания акцента.
Я думаю, что более безопасно явно указать, какие диактрисы вы хотите удалить:
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))
Comments