Sqlalchemy:从Scrapy项目动态创建表格

时间:2016-12-12 17:44:37

标签: python sqlalchemy scrapy

我正在使用sqlalchemy 1.1和scrapy。我目前正在使用管道通过sqlalchemy将提取的数据存储在sqllite表中。我想动态创建一个表来容纳被抓取的项目。

我的静态管道元素如下所示:

class SQLlitePipeline(object):

    def __init__(self):
        db_path = "sqlite:///"+settings.SETTINGS_PATH+"\\data.db"
        _engine = create_engine(db_path)
        _connection = _engine.connect()
        _metadata = MetaData()
        _stack_items = Table(table_name, _metadata,
                             Column("id", Integer, primary_key=True),
                             Column("value", Text))
                             Column("value2", Text))
        _metadata.create_all(_engine)
        self.connection = _connection
        self.stack_items = _stack_items

    def process_item(self, item, spider):

            try:
                ins_query = self.stack_items.insert().values(
                value=item['value'],
                value2=item['value2'],)
                self.connection.execute(ins_query)
            except IntegrityError:
                    print('THIS IS A DUP')
            return item

items.py:

class Filtered_Item(scrapy.Item):

    value= scrapy.Field()
    value2= scrapy.Field()

如何修改上面的管道来动态创建和插入已过滤项目的值,而不是像现在这样使用这些硬编码?

3 个答案:

答案 0 :(得分:5)

实际上有一个包可以帮助你解决这个问题。

退房:dataset: databases for lazy people

以下是该页面的摘录:

  

功能

     

自动架构:

     

如果编写的表或列在数据库中不存在,则会自动创建。

     

Upserts:

     

根据是否可以找到现有版本,可以创建或更新记录。查询助手简单   查询,例如表中的所有行或跨越的所有不同值   一组列。

     

兼容性:

     

构建在SQLAlchemy之上,数据集可以与所有主要数据库一起使用,例如SQLite,PostgreSQL和MySQL。

     

脚本导出:

     

可以根据脚本配置导出数据,使流程变得简单易复制。

答案 1 :(得分:2)

这不是问题的直接答案,而是解决问题的另一种方法。

  

如何修改上面的管道以动态创建和插入已过滤项目的值,而不是像现在这样使用这些硬编码?

我听到的是,您不希望拥有预定义的表架构以及您要根据要抓取的字段调整数据库的内容。嗯,这听起来很像你需要一个无模式数据库。

考虑切换到MongoDB或其他NoSQL无模式存储。 Scrapy文档甚至提供了一个example of a Python+MongoDB pipeline,它将一个已删除的项目作为JSON文档插入MongoDB集合(SQL术语中的“表”):

def process_item(self, item, spider):
    self.db[self.collection_name].insert(dict(item))
    return item

而且,重要的是 - item字段是什么并不重要 - 您的集合文档没有预定义的结构。

这只是一个想法 - 我不太了解您的项目要求和可能的限制。

答案 2 :(得分:2)

以下是我根据亚历克斯上面的数据集建议提出的建议:

import dataset

class DynamicSQLlitePipeline(object):

    @classmethod
    def from_crawler(cls, crawler):
        # Here, you get whatever value was passed through the "target" parameter
        table_name = getattr(crawler.spider, "target")
        return cls(table_name)

    def __init__(self,table_name):
        try:
            db_path = "sqlite:///"+settings.SETTINGS_PATH+"\\data.db"
            db = dataset.connect(db_path)
            self.my_table = db[table_name]
        except Exception:
            traceback.exec_print()

    def process_item(self, item, spider):

        try:
            self.my_table.insert(dict(item))
        except IntegrityError:
                print('THIS IS A DUP')
        return item

希望它有所帮助。