Pergunta

Eu estou aprendendo Python, e como um primeiro projeto estou tomando os feeds RSS Twitter, analisar os dados e inserir os dados em um banco de dados SQLite. Eu tenho sido capaz de analisar com êxito cada entrada de alimentação em um conteúdo variável (por exemplo, "Você deve comprar na baixa ..."), um url variável (por exemplo, u' http://bit.ly/HbFwL ') e um hashtag lista (por exemplo, #stocks', u '# bolsa', u '# finance', u '# dinheiro', u '# mkt']). Eu também tenho sido bem sucedido em inserir essas três peças de informação em três colunas separadas em um sqlite "RSSEntries" tabela, onde cada linha é uma entrada rss / Tweet diferente.

No entanto, pretende definir-se uma base de dados em que há uma relação de n para n entre as entradas rss indivíduo de alimentação (isto é, tweets individuais) e as hashtags que estão associados com cada entrada. Então, eu configurar as seguintes tabelas usando sqlalchemy (a primeira tabela inclui apenas URLs de feed RSS os twitteiros que eu quero fazer o download e de análise):

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

Até agora, eu tenho sido capaz de entrar com sucesso apenas as três principais peças de informação na tabela de RSSEntries usando o seguinte código (abreviado onde ...)

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

Agora, aqui está a grande questão. Como inserir os dados no feedtag e tagname tabelas? Este é um ponto de atrito real para mim, já que para iniciar o hasthag variável é atualmente uma lista, e cada entrada do feed poderia conter qualquer lugar entre 0 e, digamos, 6 hashtags. Eu sei como inserir a lista inteira em uma única coluna, mas não como inserir apenas os elementos da lista em colunas separadas (ou, neste exemplo, linhas). Um ponto de atrito maior é a questão geral de como inserir as hashtags individuais para o tagname mesa quando um tagname poderia ser usado em várias entradas de alimentação diferentes, e, em seguida, como ter as "associações" aparecem corretamente no feedtag mesa.

Em resumo, eu sei exatamente como cada uma das tabelas deve olhar quando está tudo feito, mas não tenho idéia de como escrever o código para obter os dados para o tagname e feedtag tabelas. O conjunto "de muitos para muitos" set-up é novo para mim.

Eu poderia realmente usar sua ajuda sobre isso. Agradecemos antecipadamente para quaisquer sugestões.

-Greg

P.S. - Editar - Graças às excelentes sugestões de Formigas Aasma, eu fui capaz de quase obter a coisa toda para o trabalho. Especificamente, o 1º e 2º sugeriu blocos de código agora funcionam bem, mas eu estou tendo um problema implementando o 3º bloco de código. Estou recebendo o seguinte erro:

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

Então, porque eu não poderia dizer onde Formigas Aasma consegui o papel "entry_id" a partir, eu tentei substituindo-o por "entries.id", pensando que isso poderia inserir o "id" da tabela "entradas". No entanto, nesse caso, eu recebo este erro:

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'

Eu não estou completamente certo onde está o problema, e eu realmente não entendo onde os "entry_id" encaixa participar, para que eu tenha colado em seguir todo o meu código "inserção" relevante. alguém ajuda pode me ver o que há de errado? Note que eu também notei que eu estava incorretamente chamando meu última tabela "feedtag_table" em vez de "entrytag_table" Isto não se encontraram com o meu objetivo inicialmente declarado de se relacionar alimentação indivíduo entradas para hashtags, ao invés de alimentos para hashtags. Eu já corrigido o código acima.

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])
Foi útil?

Solução

Em primeiro lugar, você deve usar o construtor SQLAlchemy SQL para as inserções para dar SQLAlcehemy mais conhecimento sobre o que está fazendo.

 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 inserir associações de marca ao seu esquema você precisa olhar punho para cima seus identificadores de marca e criar qualquer que não existe:

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]

Em seguida, basta inserir o ID de associado é na feedtag_table. Você pode usar o apoio executemany passando uma lista de dicts para o método execute.

conn.execute(feedtag_table.insert(),
    [{'feedid': entry_id, 'tagid': tag_ids[tag]} for tag in hashtags])
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top