¿Cuál es la mejor manera de eliminar acentos (normalizar) en una cadena Unicode de Python?
Tengo una cadena Unicode en Python y me gustaría eliminar todos los acentos (diacríticos).
Encontré en la web una manera elegante de hacer esto (en Java):
- convertir la cadena Unicode a su forma larga normalizada (con un carácter separado para letras y signos diacríticos)
- elimine todos los caracteres cuyo tipo Unicode sea "diacrítico".
¿Necesito instalar una biblioteca como pyICU o es posible solo con la biblioteca estándar de Python? ¿Y qué pasa con Python 3?
Nota importante: me gustaría evitar el código con una asignación explícita de caracteres acentuados a su contraparte no acentuada.
Unidecode es la respuesta correcta para esto. Translitera cualquier cadena Unicode a la representación más cercana posible en texto ASCII.
Ejemplo:
>>> from unidecode import unidecode
>>> unidecode('kožušček')
'kozuscek'
>>> unidecode('北亰')
'Bei Jing '
>>> unidecode('François')
'Francois'
Qué tal esto:
import unicodedata
def strip_accents(s):
return ''.join(c for c in unicodedata.normalize('NFD', s)
if unicodedata.category(c) != 'Mn')
Esto también funciona con letras griegas:
>>> strip_accents(u"A \u00c0 \u0394 \u038E")
u'A A \u0394 \u03a5'
>>>
La categoría de caracteres "Mn" significa Nonspacing_Mark
, que es similar a unicodedata.combining en la respuesta de MiniQuark (no pensé en unicodedata.combining, pero probablemente sea la mejor solución, porque es más explícita).
Y tenga en cuenta que estas manipulaciones pueden alterar significativamente el significado del texto. Los acentos, diéresis, etc. no son "decoración".
Acabo de encontrar esta respuesta en la 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
Funciona bien (para francés, por ejemplo), pero creo que el segundo paso (eliminar los acentos) podría manejarse mejor que eliminar los caracteres que no son ASCII, porque esto fallará en algunos idiomas (griego, por ejemplo). La mejor solución probablemente sería eliminar explícitamente los caracteres Unicode etiquetados como signos diacríticos.
Editar : esto funciona:
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)
devolverá verdadero si el carácter c
se puede combinar con el carácter anterior, es decir, principalmente si es un signo diacrítico.
Edición 2 : remove_accents
espera una cadena Unicode , no una cadena de bytes. Si tiene una cadena de bytes, debe decodificarla en una cadena Unicode como esta:
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)