Domanda

Sto imparando Python e come primo progetto sto prendendo i feed RSS di Twitter, analizzando i dati e inserendo i dati in un database sqlite. Sono stato in grado di analizzare con successo ogni voce del feed in una variabile content (ad es. & Quot; Dovresti acquistare a basso ... "), una variabile url (ad es. u http://bit.ly/HbFwL ') e un elenco hashtag (ad es. #stocks', u '# stockmarket', u '# finance', u '# money', u '# mkt']). Ho anche avuto successo nell'inserimento di queste tre informazioni in tre colonne separate in un sqlite "RSSEntries" tabella, in cui ogni riga è una voce / tweet rss diverso.

Tuttavia, voglio creare un database in cui esiste una relazione molti-a-molti tra le singole voci del feed rss (cioè i singoli tweet) e gli hashtag associati a ciascuna voce. Quindi, ho impostato le seguenti tabelle usando sqlalchemy (la prima tabella include solo gli URL dei feed rss di Twitterers che voglio scaricare e analizzare):

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')),
)

Finora sono stato in grado di inserire correttamente solo le tre principali informazioni nella tabella RSSEntries utilizzando il seguente codice (abbreviato dove ...)

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))

Ora, ecco l'enorme domanda. Come inserisco i dati nelle tabelle feedtag e tagname ? Questo è un vero punto critico per me, dal momento che per iniziare la variabile hasthag è attualmente un elenco e ogni voce del feed può contenere ovunque tra 0 e, diciamo, 6 hashtag. So come inserire l'intero elenco in una singola colonna ma non come inserire solo gli elementi dell'elenco in colonne separate (o, in questo esempio, righe). Un punto critico più grande è la domanda generale su come inserire i singoli hashtag nella tabella tagname quando un tagname può essere utilizzato in numerose voci di feed diverse, e quindi come avere le "associazioni" " apparire correttamente nella tabella feedtag .

In breve, so esattamente come dovrebbe apparire ciascuna delle tabelle una volta terminate, ma non ho idea di come scrivere il codice per ottenere i dati nel tagname e feedtag tabelle. L'intero "molti-a-molti" l'installazione è nuova per me.

Potrei davvero usare il tuo aiuto su questo. Grazie in anticipo per eventuali suggerimenti.

-Greg

P.S. - Modifica - Grazie agli eccellenti suggerimenti di Ants Aasma, sono stato in grado di quasi far funzionare tutto. In particolare, il 1 ° e il 2 ° blocco di codice suggerito ora funzionano correttamente, ma sto riscontrando problemi nell'implementazione del 3 ° blocco di codice. Ricevo il seguente errore:

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

Quindi, perché non riuscivo a capire dove Ants Aasma avesse ottenuto " entry_id " parte da, ho provato a sostituirlo con " entry.id " ;, pensando che questo potrebbe inserire l '"id" dalle "voci" tavolo. Tuttavia, in tal caso viene visualizzato questo errore:

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'

Non sono del tutto sicuro di dove sia il problema e non capisco davvero dove " entry_id " la parte si adatta, quindi ho incollato di seguito tutto il mio "inserimento" pertinente codice. Qualcuno può aiutarmi a vedere cosa c'è che non va? Nota che ho anche notato che stavo chiamando erroneamente la mia ultima tabella " feedtag_table " invece di " entrytag_table " Ciò non corrispondeva al mio obiettivo inizialmente dichiarato di collegare i singoli feed voci agli hashtag, piuttosto che i feed agli hashtag. Da allora ho corretto il codice sopra.

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])
È stato utile?

Soluzione

Per prima cosa, dovresti usare il builder SQLAlchemy SQL per gli inserti per dare a SQLAlcehemy maggiori informazioni su ciò che stai facendo.

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

Per inserire associazioni di tag nel tuo schema devi prima cercare i tuoi identificatori di tag e creare quelli che non esistono:

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]

Quindi inserisci semplicemente gli ID associati nel feedtag_table . È possibile utilizzare il supporto execemany passando un elenco di dicts al metodo execute.

conn.execute(feedtag_table.insert(),
    [{'feedid': entry_id, 'tagid': tag_ids[tag]} for tag in hashtags])
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top