Limpieza de cadenas de Python + Manipulación (caracteres acentuados)

Tengo una base de datos llena de nombres como:

John Smith Scott J. Holmes Dr. Kaplan Ray's Dog Levi's Adrian O'Brien Perry Sean Smyre Carie Burchfield-Thompson Björn Árnason 

Hay algunos nombres extranjeros con acentos en ellos que deben convertirse en cadenas con caracteres no acentuados.

Me gustaría convertir los nombres completos (después de eliminar caracteres como “‘”, “-“) en inicios de sesión de usuario como:

 john.smith scott.j.holmes dr.kaplan rays.dog levis adrian.obrien perry.sean.smyre carie.burchfieldthompson bjorn.arnason 

Hasta ahora tengo:

 Fullname.strip() # get rid of leading/trailing white space Fullname.lower() # make everything lower case ... # after bad chars converted/removed Fullname.replace(' ', '.') # replace spaces with periods 

Echa un vistazo a este enlace [redactado]

Aquí está el código de la página.

 def latin1_to_ascii (unicrap): """This replaces UNICODE Latin-1 characters with something equivalent in 7-bit ASCII. All characters in the standard 7-bit ASCII range are preserved. In the 8th bit range all the Latin-1 accented letters are stripped of their accents. Most symbol characters are converted to something meaningful. Anything not converted is deleted. """ xlate = { 0xc0:'A', 0xc1:'A', 0xc2:'A', 0xc3:'A', 0xc4:'A', 0xc5:'A', 0xc6:'Ae', 0xc7:'C', 0xc8:'E', 0xc9:'E', 0xca:'E', 0xcb:'E', 0xcc:'I', 0xcd:'I', 0xce:'I', 0xcf:'I', 0xd0:'Th', 0xd1:'N', 0xd2:'O', 0xd3:'O', 0xd4:'O', 0xd5:'O', 0xd6:'O', 0xd8:'O', 0xd9:'U', 0xda:'U', 0xdb:'U', 0xdc:'U', 0xdd:'Y', 0xde:'th', 0xdf:'ss', 0xe0:'a', 0xe1:'a', 0xe2:'a', 0xe3:'a', 0xe4:'a', 0xe5:'a', 0xe6:'ae', 0xe7:'c', 0xe8:'e', 0xe9:'e', 0xea:'e', 0xeb:'e', 0xec:'i', 0xed:'i', 0xee:'i', 0xef:'i', 0xf0:'th', 0xf1:'n', 0xf2:'o', 0xf3:'o', 0xf4:'o', 0xf5:'o', 0xf6:'o', 0xf8:'o', 0xf9:'u', 0xfa:'u', 0xfb:'u', 0xfc:'u', 0xfd:'y', 0xfe:'th', 0xff:'y', 0xa1:'!', 0xa2:'{cent}', 0xa3:'{pound}', 0xa4:'{currency}', 0xa5:'{yen}', 0xa6:'|', 0xa7:'{section}', 0xa8:'{umlaut}', 0xa9:'{C}', 0xaa:'{^a}', 0xab:'<<', 0xac:'{not}', 0xad:'-', 0xae:'{R}', 0xaf:'_', 0xb0:'{degrees}', 0xb1:'{+/-}', 0xb2:'{^2}', 0xb3:'{^3}', 0xb4:"'", 0xb5:'{micro}', 0xb6:'{paragraph}', 0xb7:'*', 0xb8:'{cedilla}', 0xb9:'{^1}', 0xba:'{^o}', 0xbb:'>>', 0xbc:'{1/4}', 0xbd:'{1/2}', 0xbe:'{3/4}', 0xbf:'?', 0xd7:'*', 0xf7:'/' } r = '' for i in unicrap: if xlate.has_key(ord(i)): r += xlate[ord(i)] elif ord(i) >= 0x80: pass else: r += i return r # This gives an example of how to use latin1_to_ascii(). # This creates a string will all the characters in the latin-1 character set # then it converts the string to plain 7-bit ASCII. if __name__ == '__main__': s = unicode('','latin-1') for c in range(32,256): if c != 0x7f: s = s + unicode(chr(c),'latin-1') print 'INPUT:' print s.encode('latin-1') print print 'OUTPUT:' print latin1_to_ascii(s) 

Si no tiene miedo de instalar módulos de terceros, entonces eche un vistazo al puerto de Python del módulo Perl Text::Unidecode (también está en pypi ).

El módulo no hace nada más que usar una tabla de búsqueda para transliterar los caracteres. Eché un vistazo al código y se ve muy simple. Así que supongo que está funcionando en casi cualquier sistema operativo y en cualquier versión de Python (crossfingers). También es fácil de agrupar con su aplicación.

Con este módulo, no tiene que crear su tabla de búsqueda manualmente (= riesgo reducido es incompleto).

La ventaja de este módulo en comparación con la técnica de normalización de Unicode es la siguiente: la normalización de Unicode no reemplaza a todos los caracteres. Un buen ejemplo es un personaje como “æ”. La normalización de Unicode lo verá como “Letra, minúscula” (Ll). Esto significa que usar el método de normalize le dará un carácter de reemplazo ni una sugerencia útil. Desafortunadamente, ese personaje no es representable en ASCII. Así obtendrá errores.

El módulo mencionado hace un mejor trabajo en esto. Esto reemplazará el “æ” con “ae”. Lo cual es realmente útil y tiene sentido.

Lo más impresionante que he visto es que va mucho más allá. Incluso reemplaza a los caracteres Kana japoneses en su mayoría correctamente. Por ejemplo, reemplaza “は” con “ha”. Que está perfectamente bien. Sin embargo, no es infalible ya que la versión actual reemplaza “ち” con “ti” en lugar de “chi”. Así que tendrás que manejarlo con cuidado para los personajes más exóticos.

El uso del módulo es sencillo:

 from unidecode import unidecode var_utf8 = "æは".decode("utf8") unidecode( var_utf8 ).encode("ascii") >>> "aeha" 

Tenga en cuenta que no tengo nada que ver con este módulo directamente. Simplemente sucede que me parece muy útil.

Edit: El parche que envié solucionó el error relacionado con la kana japonesa. Solo he arreglado el que pude ver de inmediato. Puede que me haya perdido un poco.

La siguiente función es genérica:

 import unicodedata def not_combining(char): return unicodedata.category(char) != 'Mn' def strip_accents(text, encoding): unicode_text= unicodedata.normalize('NFD', text.decode(encoding)) return filter(not_combining, unicode_text).encode(encoding) # in a cp1252 environment >>> print strip_accents("déjà", "cp1252") deja # in a cp1253 environment >>> print strip_accents("καλημέρα", "cp1253") καλημερα 

Obviamente, debes saber la encoding de tus cadenas.

Yo haria algo asi

 # coding=utf-8 def alnum_dot(name, replace={}): import re for k, v in replace.items(): name = name.replace(k, v) return re.sub("[^az.]", "", name.strip().lower()) print alnum_dot(u"Frédrik Holmström", { u"ö":"o", " ":"." }) 

El segundo argumento es un dictado de los caracteres que desea reemplazar, todos no az y. Los caracteres que no sean reemplazados serán eliminados.

El método de traducir le permite eliminar caracteres. Puedes usar eso para borrar caracteres arbitrarios.

 Fullname.translate(None,"'-\"") 

Si desea eliminar clases enteras de caracteres, es posible que desee utilizar el módulo re.

 re.sub('[^a-z0-9 ]', '', Fullname.strip().lower(),)