Нормализация текста unicode в имена файлов и т. д. в Python
есть ли standalonenish решения для нормализации международной кодировке Юникод для просмотра идентификаторов и имен файлов в Python?
Е. Г. включить My International Text: åäö
до my-international-text-aao
и Plone.как i18n делает действительно хорошую работу, но, к сожалению, это зависит от zope.security
и zope.publisher
и некоторые другие пакеты делают его хрупкой зависимостью.
5 ответов
то, что вы хотите сделать, также известно как "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 для использования с .перевести:
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)
выполняет декомпозицию символов Юникода, например, разбивает " ä " на две кодовые точки Юникода U+03B3
и U+0308
.
другой способ, unicodedata.category(char)
, возвращает категорию символов enicode для этого конкретного char
. Категория Mn
содержит все комбинирующие акценты, таким образом deaccent
удаляет все акценты от слов.
но обратите внимание, что это только частичное решение, оно избавляется от акцентов. Вам все еще нужен какой-то белый список символов, которые вы хотите разрешить после этого.
Я бы пошел с
https://pypi.python.org/pypi?%3Aaction=search&term=slug
трудно придумать сценарий, где один из них не соответствует вашим потребностям.