我正在学习
Python,作为第一个项目,我正在使用Twitter RSS提要,解析数据,并将数据插入到sqlite数据库中.我已经能够成功地将每个feed条目解析为内容变量(例如,“你应该买低……”),url变量(例如,u’
http://bit.ly/HbFwL‘)和一个hashtag列表(例如#stocks’) ,”#stockmarket’,”#finance’,u’#money’,u’#mkt’]).我也成功地将这三个信息插入到sqlite“RSSEntries”表中的三个单独的列中,其中每一行都是不同的rss条目/推文.
但是,我想建立一个数据库,其中各个RSS订阅源条目(即单个推文)与每个条目关联的主题标签之间存在多对多关系.所以,我使用sqlalchemy设置了下表(第一个表只包含我要下载和解析的Twitterers的RSS源):
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')),
)
到目前为止,我已经能够使用以下代码成功地将三个主要信息输入到RSSEntries表中(缩写为……)
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))
现在,这是一个很大的问题.如何将数据插入到feedtag和tagname表中?这对我来说是一个真正的难点,因为启动hasthag变量目前是一个列表,每个feed条目可以包含0到6之间的任何位置,比方说6个hashtags.我知道如何将整个列表插入到单个列中,而不是如何将列表的元素插入到单独的列中(或者,在此示例中为行).一个更大的问题是如何在标记名可用于多个不同的供稿条目时如何将单个主题标签插入标记名表,然后如何在供稿标签表中正确显示“关联”.
简而言之,我确切地知道每个表在完成后应该看起来如何,但我不知道如何编写代码以将数据放入标记名和feedtag表中.整个“多对多”设置对我来说是新的.
我真的可以用你的帮助.在此先感谢您的任何建议.
-Greg
附: – 编辑 – 感谢Ants Aasma的出色建议,我几乎可以完成所有工作.具体来说,第一个和第二个建议的代码块现在工作正常,但我在实现第三个代码块时遇到问题.我收到以下错误:
Traceback (most recent call last):
File "RSS_sqlalchemy.py", line 242, in
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
然后,因为我无法分辨Ants Aasma从哪里获得“entry_id”部分,我尝试用“entries.id”替换它,认为这可能会从“entries”表中插入“id”.但是,在这种情况下,我收到此错误:
Traceback (most recent call last):
File "RSS_sqlalchemy.py", line 242, in
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'
我不太确定问题出在哪里,而且我真的不明白“entry_id”部分的位置,所以我粘贴在所有相关的“插入”代码下面.有人可以帮我看看有什么不对吗?请注意,我也注意到我错误地调用了我的最后一个表“feedtag_table”而不是“entrytag_table”这与我最初声明的将各个订阅源条目与主题标签相关联的目标不匹配,而不是与主题标签相关.我已经纠正了上面的代码.
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])