¿Cómo puedo filtrar los caracteres Emoji de mi entrada para poder guardar en MySQL <5.5?

Tengo una aplicación Django que toma datos de tweets de la API de Twitter y los guarda en una base de datos MySQL. Por lo que sé (todavía me preocupo por los puntos más finos de la encoding de caracteres) estoy usando UTF-8 en todas partes, incluida la encoding y la comstackción de MySQL, que funciona bien, excepto cuando un tweet contiene caracteres Emoji , que entiendo Utilice una encoding de cuatro bytes. Intentar guardarlos produce las siguientes advertencias de Django:

/home/biggleszx/.virtualenvs/myvirtualenv/lib/python2.6/site-packages/django/db/backends/mysql/base.py:86: Advertencia: Valor de cadena incorrecto: ‘\ xF0 \ x9F \ x98 \ xAD I … ‘para columna’ texto ‘en la fila 1 devuelve self.cursor.execute (consulta, argumentos)

Estoy usando MySQL 5.1, así que usar utf8mb4 no es una opción a menos que actualice a 5.5, que prefiero no todavía (también por lo que he leído, el soporte de Django para esto no está del todo listo para la producción, aunque esto podría no ser más preciso). También he visto a gente recomendar el uso de BLOB en lugar de TEXTO en las columnas afectadas, lo que también preferiría no hacer ya que me imagino que perjudicaría el rendimiento.

Mi pregunta es, entonces, suponiendo que no me moleste el 100% de conservación del contenido del tweet, ¿hay alguna manera de filtrar todos los caracteres Emoji y reemplazarlos por un carácter no multibyte, como el venerable WHITE MEDIUM SMALL SQUARE (U+25FD) ? Me imagino que esta es la forma más fácil de guardar esa información dada mi configuración actual, aunque si me falta otra solución obvia, ¡me encantaría escucharla!

Para su información, estoy usando el stock Python 2.6.5 en Ubuntu 10.04.4 LTS. sys.maxunicode es 1114111, por lo que es una comstackción UCS-4.

Gracias por leer.

Resulta que esto se ha respondido unas cuantas veces, simplemente no tenía el Google-fu adecuado para encontrar las preguntas existentes.

  • Python, convierte el carácter de 4 bytes para evitar el error de MySQL “Valor de cadena incorrecto:”
  • Advertencia generada al insertar unicode de 4 bytes en mysql

Gracias a Martijn Pieters , la solución provino del mundo de las expresiones regulares, específicamente este código (basado en su respuesta al primer enlace de arriba):

 import re try: # UCS-4 highpoints = re.compile(u'[\U00010000-\U0010ffff]') except re.error: # UCS-2 highpoints = re.compile(u'[\uD800-\uDBFF][\uDC00-\uDFFF]') # mytext = u'' mytext = highpoints.sub(u'\u25FD', mytext) 

El personaje al que estoy reemplazando es el WHITE MEDIUM SMALL SQUARE (U+25FD) , para tu información, pero podría ser cualquier cosa.

Para aquellos que no están familiarizados con UCS, como yo, este es un sistema para conversión Unicode y una comstackción dada de Python incluirá soporte para la variante UCS-2 o UCS-4, cada una de las cuales tiene un límite superior diferente en el soporte de caracteres.

Con la adición de este código, las cadenas parecen persistir en MySQL 5.1 muy bien.

Espero que esto ayude a alguien más en la misma situación!

Intenté la solución de BigglesZX y no funcionó para el emoji del corazón (❤) después de leer el [artículo de wikipedia de emoji] [1] He visto que la expresión regular no cubre todos los emojis mientras que también cubre otros Rango de Unicode que no son emojis.

El siguiente código crea las 5 expresiones regulares que cubren los 5 bloques emoji en el estándar:

 emoji_symbols_pictograms = re.compile(u'[\U0001f300-\U0001f5fF]') emoji_emoticons = re.compile(u'[\U0001f600-\U0001f64F]') emoji_transport_maps = re.compile(u'[\U0001f680-\U0001f6FF]') emoji_symbols = re.compile(u'[\U00002600-\U000026FF]') emoji_dingbats = re.compile(u'[\U00002700-\U000027BF]') 

Esos bloques podrían fusionarse en tres bloques (UCS-4):

 emoji_block0 = re.compile(u'[\U00002600-\U000027BF]') emoji_block1 = re.compile(u'[\U0001f300-\U0001f64F]') emoji_block2 = re.compile(u'[\U0001f680-\U0001f6FF]') 

Sus equivalentes en UCS-2 son:

 emoji_block0 = re.compile(u'[\u2600-\u27BF]') emoji_block1 = compile(u'[\uD83C][\uDF00-\uDFFF]') emoji_block1b = compile(u'[\uD83D][\uDC00-\uDE4F]') emoji_block2 = re.compile(u'[\uD83D][\uDE80-\uDEFF]') 

Así que finalmente podemos definir una sola expresión regular con todos los casos juntos:

 import re try: # UCS-4 highpoints = re.compile(u'([\U00002600-\U000027BF])|([\U0001f300-\U0001f64F])|([\U0001f680-\U0001f6FF])') except re.error: # UCS-2 highpoints = re.compile(u'([\u2600-\u27BF])|([\uD83C][\uDF00-\uDFFF])|([\uD83D][\uDC00-\uDE4F])|([\uD83D][\uDE80-\uDEFF])') # mytext = u'' mytext = highpoints.sub(u'\u25FD', mytext) 

Descubrí por ahí otra expresión regular que es capaz de identificar los emojis. Esta es la expresión regular proporcionada por el equipo en el blog de ingeniería de instagram.

 u"(? 

Fuente: http://instagram-engineering.tumblr.com/post/118304328152/emojineering-part-2-implementing-hashtag-emoji

nota: agrego otra respuesta ya que esta no es complementaria a mi respuesta anterior aquí.

Estoy usando la función de codificador json que codifica la entrada.

esta función se utiliza para la encoding dict (para convertirla en una cadena) en json.dumps. (por lo que tenemos que hacer algunos cambios en la respuesta, eliminar el ” ”)

esto me permitió guardar emoji en mysql y presentarlo (en la web):

 # encode input from json.encoder import py_encode_basestring_ascii name = py_encode_basestring_ascii(name)[1:-1] # save YourModel.name = name name.save()