我正在学习Python,作为第一个项目,我正在使用Twitter RSS提要,解析数据,并将数据插入到sqlite数据库中。我已经能够成功地将每个订阅源条目解析为内容变量(例如,“你应该买低......”), url 变量(例如,你' http://bit.ly/HbFwL ')和 hashtag 列表(例如,#stocks',u'#stockmarket',u'#financial',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 标记名表?这对我来说是一个真正的难点,因为启动 hasthag 变量当前是一个列表,每个feed条目可以包含0到6之间的任何地方,比方说6个主题标签。我知道如何将整个列表插入到单个列中,而不是如何将列表的元素插入到单独的列中(或者,在此示例中为行)。一个更大的问题是当标记名可以在许多不同的提要条目中使用时如何将单个主题标签插入标记名表中的一般问题,然后是如何使用“关联”表。正确显示在 Feedtag 表格中。

简而言之,我确切地知道每个表在完成后应该看起来如何,但我不知道如何编写代码以将数据导入标记名 feedtag 表。整个“多对多”整个设置对我来说是新的。

我真的可以帮助你。在此先感谢您的任何建议。

-Greg

P.S。 - 编辑 - 感谢Ants Aasma的出色建议,我已经能够几乎让整个事情发挥作用。具体来说,第一个和第二个建议的代码块现在工作正常,但我在实现第三个代码块时遇到问题。我收到以下错误:

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

然后,因为我无法分辨Ants Aasma在哪里获得了“entry_id”。部分来自,我尝试将其替换为“entries.id”,认为这可能会插入“id”。来自“条目”表。但是,在这种情况下,我收到此错误:

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'

我不太确定问题出在哪里,而且我真的不明白“entry_id”的位置。部分适合,所以我粘贴在我的所有相关的“插入”之下。码。有人可以帮我看看有什么不对吗?请注意,我还注意到我错误地调用了我的上一个表格“feedtag_table”而不是“entrytag_table”这与我最初声明的将单个Feed 条目与主题标签相关联的目标不匹配,而不是与主题标签相关。我已经纠正了上面的代码。

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])
有帮助吗?

解决方案

首先,您应该使用SQLAlchemy SQL构建器进行插入,以便让SQLAlcehemy更深入地了解您正在做什么。

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

要将标记关联插入模式,您需要查找标记标识符并创建任何不存在的标记标识符:

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]

然后只需将关联的id插入 feedtag_table 即可。您可以通过将一个dicts列表传递给execute方法来使用executemany支持。

conn.execute(feedtag_table.insert(),
    [{'feedid': entry_id, 'tagid': tag_ids[tag]} for tag in hashtags])
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top