Estoy tratando de analizar una fuente RSS con el verificador de información e insertarlo en una tabla mySQL usando SQLAlchemy. De hecho, pude hacer que funcionara bien, pero hoy el feed tenía un elemento con un carácter de elipsis en la descripción y aparece el siguiente error:¿Cómo obtengo SQLAlchemy para insertar correctamente una elipsis unicode en una tabla mySQL?
UnicodeEncodeError: el códec 'latin-1' no puede codificar el carácter u ' \ u2026 'en la posición 35: ordinal no está dentro del rango (256)
Si agrego la opción convert_unicode = True al motor, puedo obtener el inserto, pero las elipsis no aparecen, es simplemente extraño caracteres. Esto parece tener sentido ya que, a mi leal saber y entender, no hay elipsis horizontal en latin-1. Incluso si configuro la codificación para utf-8, no parece marcar la diferencia. Si hago una inserción usando phpmyadmin e incluyo las elipsis, pasa bien.
Estoy pensando que simplemente no entiendo las codificaciones de caracteres o cómo obtener SQLAlchemy para usar uno que especifique. ¿Alguien sabe cómo hacer que el texto entre sin personajes extraños?
ACTUALIZACIÓN
Creo que he descubierto éste hacia fuera, pero no estoy realmente seguro de por qué es importante ...
Aquí está el código:
import sys
import feedparser
import sqlalchemy
from sqlalchemy import create_engine, MetaData, Table
COMMON_CHANNEL_PROPERTIES = [
('Channel title:','title', None),
('Channel description:', 'description', 100),
('Channel URL:', 'link', None),
]
COMMON_ITEM_PROPERTIES = [
('Item title:', 'title', None),
('Item description:', 'description', 100),
('Item URL:', 'link', None),
]
INDENT = u' '*4
def feedinfo(url, output=sys.stdout):
feed_data = feedparser.parse(url)
channel, items = feed_data.feed, feed_data.entries
#adding charset=utf8 here is what fixed the problem
db = create_engine('mysql://user:[email protected]/db?charset=utf8')
metadata = MetaData(db)
rssItems = Table('rss_items', metadata,autoload=True)
i = rssItems.insert();
for label, prop, trunc in COMMON_CHANNEL_PROPERTIES:
value = channel[prop]
if trunc:
value = value[:trunc] + u'...'
print >> output, label, value
print >> output
print >> output, "Feed items:"
for item in items:
i.execute({'title':item['title'], 'description': item['description'][:100]})
for label, prop, trunc in COMMON_ITEM_PROPERTIES:
value = item[prop]
if trunc:
value = value[:trunc] + u'...'
print >> output, INDENT, label, value
print >> output, INDENT, u'---'
return
if __name__=="__main__":
url = sys.argv[1]
feedinfo(url)
Aquí está la salida/traceback de ejecutar el código sin la opción de juego de caracteres:
Channel title: [H]ardOCP News/Article Feed
Channel description: News/Article Feed for [H]ardOCP...
Channel URL: http://www.hardocp.com
Feed items:
Item title: Windows 8 UI is Dropping the 'Start' Button
Item description: After 15 years of occupying a place of honor on the desktop, the "Start" button will disappear from ...
Item URL: http://www.hardocp.com/news/2012/02/05/windows_8_ui_dropping_lsquostartrsquo_button/
---
Item title: Which Crashes More? Apple Apps or Android Apps
Item description: A new study of smartphone apps between Android and Apple conducted over a two month period came up w...
Item URL: http://www.hardocp.com/news/2012/02/05/which_crashes_more63_apple_apps_or_android/
---
Traceback (most recent call last):
File "parse.py", line 47, in <module>
feedinfo(url)
File "parse.py", line 36, in feedinfo
i.execute({'title':item['title'], 'description': item['description'][:100]})
File "/usr/local/lib/python2.7/site-packages/sqlalchemy/sql/expression.py", line 2758, in execute
return e._execute_clauseelement(self, multiparams, params)
File "/usr/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 2304, in _execute_clauseelement
return connection._execute_clauseelement(elem, multiparams, params)
File "/usr/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1538, in _execute_clauseelement
compiled_sql, distilled_params
File "/usr/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 1639, in _execute_context
context)
File "/usr/local/lib/python2.7/site-packages/sqlalchemy/engine/default.py", line 330, in do_execute
cursor.execute(statement, parameters)
File "build/bdist.linux-i686/egg/MySQLdb/cursors.py", line 159, in execute
File "build/bdist.linux-i686/egg/MySQLdb/connections.py", line 264, in literal
File "build/bdist.linux-i686/egg/MySQLdb/connections.py", line 202, in unicode_literal
UnicodeEncodeError: 'latin-1' codec can't encode character u'\u2026' in position 35: ordinal not in range(256)
Parece que se debe agregar la c harset a la cadena de conexión mysql lo hizo. Supongo que por defecto es latin-1? Había intentado configurar la bandera de codificación en content_engine para utf8 y eso no hizo nada. ¿Alguien sabe por qué usaría latin-1 cuando las tablas y los campos están configurados en utf8 unicode? También intenté codificar el elemento ['descripción] usando .encode (' cp1252 ') antes de enviarlo y eso funcionó bien incluso sin agregar la opción de juego de caracteres a la cadena de conexión. Eso no debería haber funcionado con latin-1 pero aparentemente lo hizo? Tengo la solución, pero le encantaría una respuesta :)
¿Puedes mostrar el código que estás usando para insertarlo? ¿De dónde viene la cuerda con la elipsis? ¿El mensaje de error al usar utf-8 también dice "'latin-1' codec"? – geoffspear
Proporcione los datos que crean el problema. Si puede proporcionar el código que está utilizando, será útil comprender lo que intenta hacer. :) – Nilesh
He agregado el código sobre la cadena con la elipsis viene del sitio web hardocp.com. Aquí hay un fragmento con las elipsis: Microsoft está buscando algunas buenas ... ..ideas. He incluido mi código anterior. – kvedananda