Pregunta

Estoy aprendiendo Python, y como primer proyecto estoy tomando feeds RSS de Twitter, analizando los datos e insertando los datos en una base de datos sqlite. He podido analizar con éxito cada entrada de feed en una variable content (por ejemplo, " Debería comprar bajo ... "), una variable url (por ejemplo, u ' http://bit.ly/HbFwL '), y una lista de hashtag (por ejemplo, #stocks', u '# stockmarket', u '# finance', u '# money', u '# mkt']). También he tenido éxito al insertar estos tres datos en tres columnas separadas en un sqlite " RSSEntries " tabla, donde cada fila es una entrada / tweet rss diferente.

Sin embargo, quiero configurar una base de datos donde exista una relación de muchos a muchos entre las entradas individuales de feeds RSS (es decir, tweets individuales) y los hashtags asociados con cada entrada. Por lo tanto, configuré las siguientes tablas utilizando sqlalchemy (la primera tabla solo incluye las direcciones URL de RSS de los usuarios de Twitter que quiero descargar y analizar):

RSSFeeds = schema.Table('feeds', metadata,
    schema.Column('id', types.Integer, 
        schema.Sequence('feeds_seq_id', optional=True), primary_key=True),
    schema.Column('url', types.VARCHAR(1000), default=u''),
)

RSSEntries = schema.Table('entries', metadata,
    schema.Column('id', types.Integer, 
        schema.Sequence('entries_seq_id', optional=True), primary_key=True),
    schema.Column('feed_id', types.Integer, schema.ForeignKey('feeds.id')),
    schema.Column('short_url', types.VARCHAR(1000), default=u''),
    schema.Column('content', types.Text(), nullable=False),
    schema.Column('hashtags', types.Unicode(255)),
)

tag_table = schema.Table('tag', metadata,
    schema.Column('id', types.Integer,
       schema.Sequence('tag_seq_id', optional=True), primary_key=True),
    schema.Column('tagname', types.Unicode(20), nullable=False, unique=True)
)

entrytag_table = schema.Table('entrytag', metadata,
    schema.Column('id', types.Integer,
        schema.Sequence('entrytag_seq_id', optional=True), primary_key=True),
    schema.Column('entryid', types.Integer, schema.ForeignKey('entries.id')),
    schema.Column('tagid', types.Integer, schema.ForeignKey('tag.id')),
)

Hasta ahora, he podido ingresar con éxito solo las tres piezas principales de información en la tabla RSSEntries usando el siguiente código (abreviado donde ...)

engine = create_engine('sqlite:///test.sqlite', echo=True)
conn = engine.connect()
.........
conn.execute('INSERT INTO entries (feed_id, short_url, content, hashtags) VALUES 
    (?,?,?,?)', (id, tinyurl, content, hashtags))

Ahora, aquí está la gran pregunta. ¿Cómo inserto los datos en las tablas feedtag y tagname ? Este es un punto clave para mí, ya que para comenzar, la variable hasthag es actualmente una lista, y cada entrada de feed podría contener entre 0 y, digamos, 6 hashtags. Sé cómo insertar toda la lista en una sola columna, pero no cómo insertar solo los elementos de la lista en columnas separadas (o, en este ejemplo, filas). Un punto importante es la pregunta general de cómo insertar los hashtags individuales en la tabla tagname cuando se puede usar un tagname en numerosas entradas de feed diferentes, y luego cómo tener las asociaciones de "quot quot" aparece correctamente en la tabla feedtag .

En resumen, sé exactamente cómo deberían verse cada una de las tablas cuando se terminen, pero no tengo idea de cómo escribir el código para obtener los datos en tagname y feedtag tablas. Todo el " muchos a muchos " La configuración es nueva para mí.

Realmente podría usar tu ayuda en esto. Gracias de antemano por cualquier sugerencia.

-Greg

P.S. - Editar - Gracias a las excelentes sugerencias de Ants Aasma, he podido casi hacer que todo funcione. Específicamente, los bloques de código sugeridos primero y segundo ahora funcionan bien, pero tengo un problema al implementar el bloque de código tercero. Recibo el siguiente error:

Traceback (most recent call last):
  File "RSS_sqlalchemy.py", line 242, in <module>
    store_feed_items(id, entries)
  File "RSS_sqlalchemy.py", line 196, in store_feed_items
    [{'feedid': entry_id, 'tagid': tag_ids[tag]} for tag in hashtags2])
NameError: global name 'entry_id' is not defined

Entonces, porque no podía saber de dónde sacó Ants Aasma " entry_id " parte de, intenté reemplazarlo con " entries.id " ;, pensando que esto podría insertar el " id " de las entradas " " mesa. Sin embargo, en ese caso me sale este error:

Traceback (most recent call last):
  File "RSS_sqlalchemy.py", line 242, in <module>
    store_feed_items(id, entries)
  File "RSS_sqlalchemy.py", line 196, in store_feed_items
    [{'feedid': entries.id, 'tagid': tag_ids[tag]} for tag in hashtags2])
AttributeError: 'list' object has no attribute 'id'

No estoy muy seguro de dónde está el problema, y ??realmente no entiendo dónde está " entry_id " la parte encaja, así que he pegado debajo de toda mi " inserción " " relevante; código. ¿Puede alguien ayudarme a ver qué está mal? Tenga en cuenta que también me di cuenta de que estaba llamando incorrectamente a mi última tabla " feedtag_table " en lugar de " entrytag_table " Esto no coincidía con mi objetivo inicial de relacionar las entradas de fuentes individuales a los hashtags, en lugar de las fuentes a los hashtags. Desde entonces he corregido el código anterior.

feeds = conn.execute('SELECT id, url FROM feeds').fetchall()

def store_feed_items(id, items):
    """ Takes a feed_id and a list of items and stored them in the DB """
    for entry in items:
        conn.execute('SELECT id from entries WHERE short_url=?', (entry.link,))
        s = unicode(entry.summary) 
        test = s.split()
        tinyurl2 = [i for i in test if i.startswith('http://')]
        hashtags2 = [i for i in s.split() if i.startswith('#')]
        content2 = ' '.join(i for i in s.split() if i not in tinyurl2+hashtags2)
        content = unicode(content2)
        tinyurl = unicode(tinyurl2)
        hashtags = unicode (hashtags2)
        date = strftime("%Y-%m-%d %H:%M:%S",entry.updated_parsed)

        conn.execute(RSSEntries.insert(), {'feed_id': id, 'short_url': tinyurl,
            'content': content, 'hashtags': hashtags, 'date': date})    

        tags = tag_table
        tag_id_query = select([tags.c.tagname, tags.c.id], tags.c.tagname.in_(hashtags))
        tag_ids = dict(conn.execute(tag_id_query).fetchall())
        for tag in hashtags:
            if tag not in tag_ids:
                result = conn.execute(tags.insert(), {'tagname': tag})
                tag_ids[tag] = result.last_inserted_ids()[0]

        conn.execute(entrytag_table.insert(),
            [{'feedid': id, 'tagid': tag_ids[tag]} for tag in hashtags2])
¿Fue útil?

Solución

Primero, debes usar el generador de SQL de SQLAlchemy para las inserciones para darle a SQLAlcehemy más información sobre lo que estás haciendo.

 result = conn.execute(RSSEntries.insert(), {'feed_id': id, 'short_url': tinyurl,
        'content': content, 'hashtags': hashtags, 'date': date})
 entry_id = result.last_insert_ids()[0]

Para insertar asociaciones de etiquetas en su esquema, primero debe buscar sus identificadores de etiquetas y crear cualquiera que no exista:

tags = tag_table
tag_id_query = select([tags.c.tagname, tags.c.id], tags.c.tagname.in_(hashtags))
tag_ids = dict(conn.execute(tag_id_query).fetchall())
for tag in hashtags:
    if tag not in tag_ids:
        result = conn.execute(tags.insert(), {'tagname': tag})
        tag_ids[tag] = result.last_inserted_ids()[0]

Luego, solo inserte los ID asociados en feedtag_table . Puede usar el soporte de ejecución al pasar una lista de dictados al método de ejecución.

conn.execute(feedtag_table.insert(),
    [{'feedid': entry_id, 'tagid': tag_ids[tag]} for tag in hashtags])
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top