Scrapy 最佳实践

Scrapy 最佳实践,scrapy,Scrapy,我正在使用scrapy下载大量数据。我使用默认的16个并发请求。 如指南所示,我使用pipelines方法process\u item在共享变量处收集数据。在close\u spider将数据保存到SQL。 如果我加载的网站太大,我会丢失所有的系统内存。 我应该如何避免这个问题 现在我使用了一个DB连接,它是在open\u spider方法中准备的,我不能在每个进程项目中同时使用它。在管道中创建一个已删除项目的列表,一旦该列表的大小大于N,然后调用DB函数来保存数据。这里是我的项目100%的工作

我正在使用scrapy下载大量数据。我使用默认的16个并发请求。 如指南所示,我使用pipelines方法
process\u item
在共享变量处收集数据。在
close\u spider
将数据保存到SQL。 如果我加载的网站太大,我会丢失所有的系统内存。 我应该如何避免这个问题


现在我使用了一个DB连接,它是在
open\u spider
方法中准备的,我不能在每个
进程项目中同时使用它。

在管道中创建一个已删除项目的列表,一旦该列表的大小大于N,然后调用DB函数来保存数据。这里是我的项目100%的工作代码。请参见
close_spider()
,在spider关闭时,
self.items
中的项目可能少于N个,因此当spider关闭时,
self.items
列表中的任何剩余数据也将保存在DB中

from scrapy import signals

class YourPipeline(object):

    def __init__(self):
        self.items = []

    def process_item(self, item, spider):

        self.items.extend([ item ])

        if len(self.items) >= 50:
            self.insert_current_items(spider)   
        return item

    def insert_current_items(self, spider):
        for item in self.items:
            update_query = ', '.join(["`" + key + "` = %s " for key, value in item.iteritems()])

            query = "SELECT asin FROM " + spider.tbl_name + " WHERE asin = %s LIMIT 1"

            spider.cursor.execute(query, (item['asin']))

            existing = spider.cursor.fetchone()

            if spider.cursor.rowcount > 0:

                query = "UPDATE " + spider.tbl_name + " SET " + update_query + ", date_update = CURRENT_TIMESTAMP WHERE asin = %s"

                update_query_vals = list(item.values())
                update_query_vals.extend([existing['YOUR_UNIQUE_COLUMN']])


                try:
                    spider.cursor.execute(query, update_query_vals)
                except Exception as e:
                    if 'MySQL server has gone away' in str(e):
                        spider.connectDB()
                        spider.cursor.execute(query, update_query_vals)
                    else:
                        raise e

            else:

                # This ELSE is likely never to get executed because we are not scraping ASINS from Amazon website, we just import ASINs into DB from another script
                try:
                    placeholders = ', '.join(['%s'] * len(item))
                    columns = ', '.join(item.keys())
                    query = "INSERT INTO %s ( %s ) VALUES ( %s )" % (spider.tbl_name, columns, placeholders)
                    spider.cursor.execute(query, item)
                except Exception as e:
                    if 'MySQL server has gone away' in str(e):
                        spider.connectDB()
                        spider.cursor.execute(query, item)
                    else:
                        raise e


        self.items = []



    def close_spider(self, spider):
        self.insert_current_items(spider)

正如我的意思,您也有许多并发请求。他们每个人都将self.items的大小增加了一个。当它们的大小变为50时,最接近的进程项刷新列表。但是如果insert_current_items仍在执行,而self.items和other收集了其他50个项目,该怎么办呢。因此,将有一些insert\u current\u items方法同时工作,不是吗?
self.items
是一个全局变量,所以无论调用多少次或并发处理\u item方法,您都不会有问题,但我的意思是spider.cursor.execute(query,update\u query\u vals)方法中的问题,它能同时工作很多次吗?