在Scrapy中使用Sqlalchemy更新表行
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Scrapy中使用Sqlalchemy更新表行相关的知识,希望对你有一定的参考价值。
我正在使用scrapy和sqlalchemy。在我的Spider中,我从一个表中选择并创建请求:
def start_requests(self):
db_path = "sqlite:///"+settings.SETTINGS_PATH+"\data.db"
source_table= self.table
engine = create_engine(db_path)
Base = declarative_base()
# metadata = Base.metadata
# Look up the existing tables from database
Base.metadata.reflect(engine)
# Create class that maps via ORM to the database table
table = type(source_table, (Base,), {'__tablename__': source_table})
Session = sessionmaker(bind=engine)
session = Session()
i = 0
for row in session.query(table).filter(table.url.contains('http')).limit(3):
i += 1
print(row.url)
yield Request(url=row.url, headers= headers, callback=self.get_PDF,meta={'session': session,'row': row, 'cookiejar': i },dont_filter = True)
正如您所看到的,我正在通过每个scrapy请求传递sqlalchemy行对象。每行对象包含我从scrapy响应更新的空白字段。
def get_PDF(self, response):
row = response.meta['row']
row.field1 = response.field1 # simplified pseudocode
现在我想更新行对象,以便将其更改存储在db中。如果我传递会话对象,我可以做session.commit()。使用row_object执行此操作的最佳方法是什么?我需要传递会话对象吗?
编辑:我已经更改了我的蜘蛛以传递会话对象:
def get_PDF(self, response):
row = response.meta['row']
session = response.meta['session']
row =process_output(o, row)
session.add(row)
session.commit()
答案
我想说总是处理数据库和“外部”存储的最好方法是使用Pipeline
,因为它是一种分离代码逻辑的方法。 Pipeline只处理蜘蛛返回的项目,因此您无需担心蜘蛛代码中的请求或内容。
此外,Pipeline创建了一个与爬虫相关联的对象,它只被实例化一次,这对于这个session
情况非常有用。
如果您需要以不同方式处理项目,则始终可以向每个项目发送唯一标识符,因此管道知道如何处理每个项目。
编辑:用于在蜘蛛内创建Session
对象,并在管道中重用它,你可以这样做:
蜘蛛:
def start_requests(self):
self.session = Session()
管道
def process_item(self, item, spider):
...
spider.session.commit()
spider
是整个爬虫的“唯一”蜘蛛实例,所以你可以在那里使用它的属性。
以上是关于在Scrapy中使用Sqlalchemy更新表行的主要内容,如果未能解决你的问题,请参考以下文章