¿Dónde está la base de datos “mejor ASCII para este Unicode” de Python?

85

Tengo un texto que usa puntuación Unicode, como comillas dobles a la izquierda, comillas simples a la derecha para apóstrofo, etc., y lo necesito en ASCII. ¿Python tiene una base de datos de estos caracteres con sustitutos ASCII obvios para que pueda hacerlo mejor que convertirlos todos en "?" ?

joeforker
fuente
21
Eres un valiente guerrero. Unicode es el archienemigo de Python.
David Berger
2
Las personas que encuentren esto podrían estar interesadas en ¿Cuál es la mejor manera de eliminar los acentos en una cadena Unicode de Python?
Martin Thoma

Respuestas:

89

Unidecode parece una solución completa. Convierte citas elegantes en citas ascii, caracteres latinos acentuados en sin acentos e incluso intenta la transliteración para tratar con caracteres que no tienen equivalentes ASCII. De esa manera, sus usuarios no tendrán que ver muchos? cuando tenía que pasar su texto a través de un sistema ascii de 7 bits heredado.

>>> from unidecode import unidecode
>>> print unidecode(u"\u5317\u4EB0")
Bei Jing 

http://www.tablix.org/~avian/blog/archives/2009/01/unicode_transliteration_in_python/

joeforker
fuente
3
Hm ... las diéresis alemanas se convierten a su carácter base en lugar de, por ejemplo, ö = oe, ä = ae, etc.
ThiefMaster
4
@ThiefMaster, ¿esos equivalentes son verdaderos en todos los idiomas? Tal vez Unidecode vaya por el mínimo común denominador.
Mark Ransom
Unidecode ciertamente apuesta por la solución independiente del idioma. Para una solución centrada en el alemán, convierta los caracteres aplicables manualmente ( s/ö/oe/, etc.) antes de limpiar el resto con unidecode.
Alexis
4
De hecho, en finlandés, por ejemplo, mientras ä -> a, ö -> oes francamente mal, todavía es preferible aeyoe
Antti Haapala
25

En mi respuesta original, también sugerí unicodedata.normalize. Sin embargo, decidí probarlo y resulta que no funciona con comillas Unicode. Hace un buen trabajo traduciendo caracteres Unicode acentuados, así que supongo que unicodedata.normalizese implementa usando la unicode.decompositionfunción, lo que me lleva a creer que probablemente solo puede manejar caracteres Unicode que son combinaciones de una letra y un signo diacrítico, pero no lo soy un experto en la especificación Unicode, por lo que podría estar lleno de aire caliente ...

En cualquier caso, puede utilizar unicode.translatepara tratar con caracteres de puntuación. El translatemétodo toma un diccionario de ordinales Unicode a ordinales Unicode, por lo que puede crear una asignación que traduzca la puntuación solo Unicode a puntuación compatible con ASCII:

'Maps left and right single and double quotation marks'
'into ASCII single and double quotation marks'
>>> punctuation = { 0x2018:0x27, 0x2019:0x27, 0x201C:0x22, 0x201D:0x22 }
>>> teststring = u'\u201Chello, world!\u201D'
>>> teststring.translate(punctuation).encode('ascii', 'ignore')
'"hello, world!"'

Puede agregar más asignaciones de puntuación si es necesario, pero no creo que deba preocuparse necesariamente por el manejo de cada carácter de puntuación Unicode. Si usted no necesita acentos mango y otros signos diacríticos, todavía se puede utilizar unicodedata.normalizepara hacer frente a esos personajes.

Mike Spross
fuente
21

Interesante pregunta.

Google me ayudó a encontrar esta página que describe el uso del módulo unicodedata de la siguiente manera:

import unicodedata
unicodedata.normalize('NFKD', title).encode('ascii','ignore')
caballete
fuente
3

Hay una discusión adicional sobre esto en http://code.activestate.com/recipes/251871/ que tiene la solución NFKD y algunas formas de hacer una tabla de conversión, para cosas como ± => +/- y otros caracteres que no son letras.

Andrew Dalke
fuente