remove - ¿Cuál es la mejor manera de eliminar los acentos en una cadena Unicode de Python?
quitar acentos python 3 (9)
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 que están etiquetados como diacríticos.
Edición : esto hace el truco:
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
puede combinarse con el carácter anterior, es decir, principalmente si es un 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)
Tengo una cadena Unicode en Python, y me gustaría eliminar todos los acentos (diacríticos).
Encontré en la Web una forma elegante de hacer esto en Java:
- convertir la cadena Unicode a su forma normalizada larga (con un carácter separado para letras y signos diacríticos)
- eliminar todos los caracteres cuyo tipo de Unicode es "diacrítico".
¿Necesito instalar una biblioteca como pyICU o esto es posible solo con la biblioteca estándar de python? ¿Y qué hay de 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.
Algunos idiomas tienen la combinación de signos diacríticos como letras de idioma y acentos diacríticos para especificar el acento.
Creo que es más seguro especificar explícitamente qué diactricos quieres despojar:
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))
En realidad, trabajo en Python 2.6, 2.7 y 3.4 compatible con el proyecto y tengo que crear ID a partir de entradas de usuario gratuitas.
Gracias a ti, he creado esta función que hace maravillas.
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
resultado:
text_to_id("Montréal, über, 12.89, Mère, Françoise, noël, 889")
>>> ''montreal_uber_1289_mere_francoise_noel_889''
En respuesta a la respuesta de @ MiniQuark:
Intentaba leer en un archivo csv que era mitad francés (con acentos) y también algunas cadenas que eventualmente se convertirían en números enteros y flotantes. Como prueba, creé un archivo test.txt
que tenía este aspecto:
Montréal, über, 12.89, Mère, Françoise, noël, 889
Tuve que incluir las líneas 2
y 3
para que funcionara (lo que encontré en un ticket de python), así como incorporar el comentario de @ 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)
El resultado:
Montreal
uber
12.89
Mere
Francoise
noel
889
(Nota: Estoy en Mac OS X 10.8.4 y uso Python 2.7.3)
Esto no solo maneja los acentos, sino también los "trazos" (como en ø, etc.):
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)
Esta es la forma más elegante en la que puedo pensar (y ha sido mencionada por alexis en un comentario en esta página), aunque no creo que sea muy elegante.
Todavía hay letras especiales que no se manejan con esto, como las letras giradas e invertidas, ya que su nombre de Unicode no contiene "CON". Depende de lo que quieras hacer de todos modos. A veces necesitaba acentos para lograr el orden del diccionario.
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 funciona también en 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.combinando en la respuesta de MiniQuark (no pensé en unicodedata.combinando, 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. Acentos, Umlauts, etc. no son "decoración".
Unidecode es la respuesta correcta para esto. Transcribe cualquier cadena de Unicode a la representación más cercana posible en texto ASCII.
Ejemplo:
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''
gensim.utils.deaccent(text) de Gensim - modelado de temas para humanos :
deaccent("Šéf chomutovských komunistů dostal poštou bílý prášek") ''Sef chomutovskych komunistu dostal postou bily prasek''
Otra solución es Unidecode .
No es que la solución sugerida con unicodedata generalmente elimine los acentos en algunos caracteres (por ejemplo, convierte ''ł''
en ''''
, en lugar de ''l''
).
import unicodedata
s = ''Émission''
search_string = ''''.join((c for c in unicodedata.normalize(''NFD'', s) if unicodedata.category(c) != ''Mn''))
Para Python 3.X
print (search_string)
Para Python 2.X
print search_string