Нормализация текста Unicode для имен файлов и т. Д. В Python

Существуют ли автономные решения для нормализации международного текста юникода для надежных идентификаторов и имен файлов в Python?

Например, My International Text: åäö to my-international-text-aao

plone.i18n действительно хорошо работает, но, к сожалению, это зависит от zope.publisher и zope.publisher и некоторых других пакетов, что делает его хрупкой зависимостью.

Некоторые операции, которые применяются plone.i18n

  • Поведение юникода на Python в Google App Engine
  • UnicodeEncodeError: кодек «gbk» не может кодировать символ: незаконная многобайтовая последовательность
  • Замените символы пунктуации полной ширины эквивалентными эквивалентами ширины
  • Лучший способ конвертировать URL-адрес Unicode в ASCII (UTF-8-escaped) в Python?
  • MIMEText UTF-8 кодирует проблемы при отправке электронной почты
  • UTF-8 В протоколе Python, как?
  • json.dump - UnicodeDecodeError: кодек 'utf8' не может декодировать байт 0xbf в позиции 0: недопустимый стартовый байт
  • Python - Как изменить байты в файле
  • 5 Solutions collect form web for “Нормализация текста Unicode для имен файлов и т. Д. В Python”

    То, что вы хотите сделать, также известно как «slugify» строка. Вот возможное решение:

     import re from unicodedata import normalize _punct_re = re.compile(r'[\t !"#$%&\'()*\-/<=>?@\[\\\]^_`{|},.:]+') def slugify(text, delim=u'-'): """Generates an slightly worse ASCII-only slug.""" result = [] for word in _punct_re.split(text.lower()): word = normalize('NFKD', word).encode('ascii', 'ignore') if word: result.append(word) return unicode(delim.join(result)) 

    Применение:

     >>> slugify(u'My International Text: åäö') u'my-international-text-aao' 

    Вы также можете изменить разделитель:

     >>> slugify(u'My International Text: åäö', delim='_') u'my_international_text_aao' 

    Источник: Создание слизней

    Для Python 3: pastebin.com/ft7Yb3KS (спасибо @MrPoxipol ).

    Способ решения этой проблемы – принять решение о том, какие символы разрешены (разные системы имеют разные правила для действительных идентификаторов.

    После того, как вы решите, какие символы разрешены, напишите допустимый () предикат и подклассом dict для использования с str.translate :

     def makesafe(text, allowed, substitute=None): ''' Remove unallowed characters from text. If *substitute* is defined, then replace the character with the given substitute. ''' class D(dict): def __getitem__(self, key): return key if allowed(chr(key)) else substitute return text.translate(D()) 

    Эта функция очень гибкая. Это позволит вам легко определить правила для определения того, какой текст хранится и какой текст либо заменить, либо удалить.

    Вот простой пример, использующий правило: «Разрешить только символы, которые находятся в категории Юникод L»:

     import unicodedata def allowed(character): return unicodedata.category(character).startswith('L') print(makesafe('the*ides&of*march', allowed, '_')) print(makesafe('the*ides&of*march', allowed)) 

    Этот код обеспечивает безопасный вывод следующим образом:

     the_ides_of_march theidesofmarch 

    Следующие будут удалять акценты из любых символов Unicode, которые могут разлагаться на объединение пар, отбрасывать любые странные символы, которые он не может, и пробелы ядер:

     # encoding: utf-8 from unicodedata import normalize import re original = u'ľ š č ť ž ý á í é' decomposed = normalize("NFKD", original) no_accent = ''.join(c for c in decomposed if ord(c)<0x7f) no_spaces = re.sub(r'\s', '_', no_accent) print no_spaces # output: l_s_c_t_z_y_a_i_e 

    Он не пытается избавиться от символов, запрещенных файловыми системами, но вы можете украсть DANGEROUS_CHARS_REGEX из файла, который вы связали для этого.

    Я тоже брошу свое (частичное) решение:

     import unicodedata def deaccent(some_unicode_string): return u''.join(c for c in unicodedata.normalize('NFD', some_unicode_string) if unicodedata.category(c) != 'Mn') 

    Это не делает все, что вы хотите, но дает несколько приятных трюков, завернутых в удобном методе: unicode.normalise('NFD', some_unicode_string) выполняет разложение символов в unicode.normalise('NFD', some_unicode_string) , например, он разбивает 'ä' на два кодовых пункта unicode U+03B3 и U+0308 .

    Другой метод, unicodedata.category(char) , возвращает категорию символов enicode для этого конкретного char . Категория Mn содержит все сочетания акцентов, таким образом, deaccent удаляет все акценты из слов.

    Но обратите внимание, что это всего лишь частичное решение, оно избавляется от акцентов. Вам по-прежнему нужен какой-то белый список символов, который вы хотите разрешить после этого.

    Я бы пошел с

    https://pypi.python.org/pypi?%3Aaction=search&term=slug

    Его трудно придумать сценарий, когда один из них не соответствует вашим потребностям.

    Python - лучший язык программирования в мире.