Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用sqlite、sqlalchemy和python在数据库中重复插入_Python_Sqlite_Twitter_Sqlalchemy_Duplicates - Fatal编程技术网

使用sqlite、sqlalchemy和python在数据库中重复插入

使用sqlite、sqlalchemy和python在数据库中重复插入,python,sqlite,twitter,sqlalchemy,duplicates,Python,Sqlite,Twitter,Sqlalchemy,Duplicates,我正在学习Python,通过在线资源和网站上的人员的帮助,我掌握了Python的诀窍。在我的第一个脚本中,我正在解析Twitter RSS提要条目并将结果插入数据库,但还有一个问题我无法解决。也就是说,将重复条目插入其中一个表中 作为一个背景,我最初在HalOtis.com上找到了一个用于下载RSS提要的基本脚本,然后以几种方式对其进行了修改:1)修改以考虑Twitter RSS提要中的特性(它没有分为内容、标题、URL等);2) 为“hashtags”和多对多关系(entry_tag tabl

我正在学习Python,通过在线资源和网站上的人员的帮助,我掌握了Python的诀窍。在我的第一个脚本中,我正在解析Twitter RSS提要条目并将结果插入数据库,但还有一个问题我无法解决。也就是说,将重复条目插入其中一个表中

作为一个背景,我最初在HalOtis.com上找到了一个用于下载RSS提要的基本脚本,然后以几种方式对其进行了修改:1)修改以考虑Twitter RSS提要中的特性(它没有分为内容、标题、URL等);2) 为“hashtags”和多对多关系(entry_tag table)添加了表;3) 将表格设置更改为sqlalchemy;4) 对出现的奇怪的unicode问题进行了一些特别更改。结果,代码有些地方很难看,但它一直是一个很好的学习体验,现在可以工作了——只是它不断在“entries”表中插入重复项

因为我不确定什么对人们最有帮助,所以我在下面粘贴了整个代码,并在一些地方添加了一些注释,以指出我认为最重要的内容

我真的非常感谢你在这方面的帮助。谢谢

编辑:有人建议我为数据库提供一个模式。我以前从未这样做过,所以如果我做得不对,请容忍我。我准备了四张桌子:

  • RSSFeeds,其中包含Twitter RSS源的列表
  • RSSEntries,其中包含从每个提要下载(解析后)的单个条目列表(包含内容、hashtags、日期、url列)
  • 标签,其中包含在单个条目(Tweets)中找到的所有hashtag的列表
  • entry_标记,它包含允许我将标记映射到条目的列 简而言之,下面的脚本从RSS提要表中获取五个测试RSS提要,从每个提要下载20个最新条目/tweet,解析条目,并将信息放入RSS条目、标记和条目标记表中

    #!/usr/local/bin/python
    
    import sqlite3
    import threading
    import time
    import Queue
    from time import strftime
    import re       
    from string import split 
    import feedparser 
    from django.utils.encoding import smart_str, smart_unicode      
    from sqlalchemy import schema, types, ForeignKey, select, orm
    from sqlalchemy import create_engine
    
    engine = create_engine('sqlite:///test98.sqlite', echo=True)
    metadata = schema.MetaData(engine)   
    metadata.bind = engine
    
    def now():
        return datetime.datetime.now()
    
    
    #set up four tables, with many-to-many relationship
    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)),
        schema.Column('date', types.String()),  
    )
    
    
    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')),
    )
    
    
    metadata.create_all(bind=engine, checkfirst=True)
    
    
    # Insert test set of Twitter RSS feeds
    stmt = RSSFeeds.insert()
    stmt.execute(
        {'url': 'http://twitter.com/statuses/user_timeline/14908909.rss'},
        {'url': 'http://twitter.com/statuses/user_timeline/52903246.rss'},
        {'url': 'http://twitter.com/statuses/user_timeline/41902319.rss'},
        {'url': 'http://twitter.com/statuses/user_timeline/29950404.rss'},
        {'url': 'http://twitter.com/statuses/user_timeline/35699859.rss'},
    )
    
    
    
    #These 3 lines for threading process (see HalOtis.com for example) 
    THREAD_LIMIT = 20
    jobs = Queue.Queue(0)
    rss_to_process = Queue.Queue(THREAD_LIMIT)
    
    
    #connect to sqlite database and grab the 5 test RSS feeds
    conn = engine.connect()
    feeds = conn.execute('SELECT id, url FROM feeds').fetchall()
    
    #This block contains all the parsing and DB insertion 
    def store_feed_items(id, items):
        """ Takes a feed_id and a list of items and stores them in the DB """
        for entry in items:
            conn.execute('SELECT id from entries WHERE short_url=?', (entry.link,))
            #note: entry.summary contains entire feed entry for Twitter, 
                        #i.e., not separated into content, etc.
            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)
            print hashtags
            date = strftime("%Y-%m-%d %H:%M:%S",entry.updated_parsed)
    
    
            #Insert parsed feed data into entries table 
                        #THIS IS WHERE DUPLICATES OCCUR
            result = conn.execute(RSSEntries.insert(), {'feed_id': id, 'short_url': tinyurl,
                'content': content, 'hashtags': hashtags, 'date': date})
            entry_id = result.last_inserted_ids()[0]
    
    
            #Look up tag identifiers and create any that don't exist:
            tags = tag_table
            tag_id_query = select([tags.c.tagname, tags.c.id], tags.c.tagname.in_(hashtags2))
            tag_ids = dict(conn.execute(tag_id_query).fetchall())
            for tag in hashtags2:
                if tag not in tag_ids:
                    result = conn.execute(tags.insert(), {'tagname': tag})
                    tag_ids[tag] = result.last_inserted_ids()[0]
    
            #insert data into entrytag table 
            if hashtags2: conn.execute(entrytag_table.insert(),
                [{'entryid': entry_id, 'tagid': tag_ids[tag]} for tag in hashtags2])
    
    
    #Rest of file completes the threading process     
    def thread():
        while True:
            try:
                id, feed_url = jobs.get(False) # False = Don't wait
            except Queue.Empty:
                return
    
            entries = feedparser.parse(feed_url).entries
            rss_to_process.put((id, entries), True) # This will block if full
    
    for info in feeds: # Queue them up
        jobs.put([info['id'], info['url']])
    
    for n in xrange(THREAD_LIMIT):
        t = threading.Thread(target=thread)
        t.start()
    
    while threading.activeCount() > 1 or not rss_to_process.empty():
        # That condition means we want to do this loop if there are threads
        # running OR there's stuff to process
        try:
            id, entries = rss_to_process.get(False, 1) # Wait for up to a second
        except Queue.Empty:
            continue
    
        store_feed_items(id, entries)
    

    看起来您将SQLAlchemy包含到了以前存在的未使用SQLAlchemy的脚本中。这里有太多的运动部件,显然我们都不太了解

    我建议从零开始。不要使用线程。不要使用炼金术。首先,可能甚至不使用SQL数据库。编写一个脚本,使用简单循环和time.sleep()以尽可能简单的方式将所需信息收集到一个简单的数据结构中。然后,当这起作用时,您可以将存储添加到SQL数据库中,我真的不认为直接编写SQL语句比使用ORM困难得多,而且调试IMHO更容易。您很有可能永远不需要添加线程


    “如果你认为自己足够聪明,可以编写多线程程序,那你就不行了。”——James Ahlstrom。

    如果你提供了一个模式,这样我们就不必从源代码中推断出来,那会有所帮助。谢谢——我将在上面添加一些内容。