Sto cercando di analizzare un feed RSS con feedparser e inserirlo in una tabella mySQL utilizzando SQLAlchemy. In realtà sono riuscito a farlo funzionare correttamente ma oggi il feed aveva un carattere con un puntino di sospensione nella descrizione e ricevo il seguente errore:Come si ottiene SQLAlchemy per inserire correttamente i puntini di sospensione di unicode in una tabella mySQL?
UnicodeEncodeError: il codec 'latin-1' non può codificare il carattere u ' \ u2026 'in posizione 35: ordinale non compreso nell'intervallo (256)
Se aggiungo l'opzione convert_unicode = True al motore, riesco a far passare l'inserto ma i puntini di sospensione non vengono visualizzati è solo strano personaggi. Questo sembra avere senso dato che, per quanto ne so, non ci sono ellissi orizzontali in latino-1. Anche se imposto la codifica su utf-8, non sembra che faccia la differenza. Se faccio un inserto usando phpmyadmin e includo i puntini di sospensione va bene.
Sto pensando di non capire le codifiche dei caratteri o come ottenere SQLAlchemy per usarne uno che specifichi. Qualcuno sa come ottenere il testo senza caratteri strani?
UPDATE
Credo di aver capito questo fuori, ma io non sono davvero sicuro perché è importante ...
Ecco il codice:
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)
ecco l'output/traceback di eseguire il codice senza l'opzione charset:
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)
così sembra che l'aggiunta della c harset alla stringa mysql connect lo ha fatto. Suppongo che sia impostato su Latin-1? Ho provato a impostare il flag di codifica su content_engine su utf8 e questo non ha fatto nulla. Qualcuno sa perché userebbe latin-1 quando le tabelle e i campi sono impostati su unicode utf8? Ho anche provato a codificare l'oggetto ['description] usando .encode (' cp1252 ') prima di inviarlo e anche quello ha funzionato senza aggiungere l'opzione charset alla stringa di connessione. Questo non avrebbe dovuto funzionare con Latin-1 ma apparentemente lo ha fatto? Ho la soluzione, ma mi piacerebbe una risposta :)
Puoi mostrare il codice che stai utilizzando per inserirlo? Dov'è la corda con l'ellissi? Il messaggio di errore quando si usa utf-8 dice anche "codec" latin-1 "? – geoffspear
Si prega di fornire i dati che creano problemi. Se riesci a fornire il codice che stai usando, sarà utile capire cosa stai cercando di fare. :) – Nilesh
Ho aggiunto il codice sopra la stringa con i puntini di sospensione proveniente dal sito Web hardocp.com. Ecco uno snippet con i puntini di sospensione: Microsoft sta cercando alcuni buoni ... ..ideas. Ho incluso il mio codice qui sopra. – kvedananda