将多个蜘蛛的输出捕获到单个输出文件/变量中的正确 'scrapy' 方法是什么?
What is the correct 'scrapy' way to capture the output of multiple spiders into a single output file / variable?
我是 Scrapy 的新手,正在尝试了解我如何输出数据 post-抓取。我已经阅读了一些文档,但我很难理解它,而且可用的文档对于我的用例来说有点模糊。
基本上,我同时启动了大约九个蜘蛛,以从给定网站上抓取某些信息。我按如下方式启动抓取:
from scrapy.utils import project
from scrapy.crawler import CrawlerProcess
# Initialise a crawler
crawl_process = CrawlerProcess(project.get_project_settings())
# Locate and iterate through the spiders
for spider in (x for x in crawl_process.spider_loader.list()):
crawl_process.crawl(spider)
# Kick it off
crawl_process.start()
这些蜘蛛的输出是每个蜘蛛的一个字典(如果有匹配),类似于以下内容:
yield {
'Retailer': 'Amazon',
'Item': 'Product Example',
'Price': '£62.50',
'URL': 'URL'
}
我想尽可能避免写入磁盘,因为这个脚本将 运行 在我的 Raspberry Pi 的 SD 卡上,所以每两个一次写入数十个文件大约几分钟并不理想。
我的要求:
我希望能够找到一种方法来收集内存中的数据,直到所有的蜘蛛都完成,然后我需要能够创建一个字典列表进行比较,最后输出到一个单一的json 文件。这是可能吗?真是摸不着头脑。
如果不可能,我真的很想知道如何正确处理它。
利用 Scrapy Pipeline + MongoDB Cloud 是一个很好的选择。将流水线用于任何逻辑,并将您需要的内容写入 MongoDB.
您也可以只将所有内容添加到 MongoDB 并使用 Pymongo 和一些简单的脚本编写所有逻辑。
选项 2 的管道类似于:
import pymongo
from itemadapter import ItemAdapter
class MongoPipeline:
collection_name = 'scrapy_items'
def open_spider(self, spider):
self.client = pymongo.MongoClient(os.environ.get("MONGO_DB_CONNECTION_STRING"))
self.db = self.client["db name"]
def close_spider(self, spider):
self.client.close()
def process_item(self, item, spider):
self.db[self.collection_name].insert_one(ItemAdapter(item).asdict())
return item
MongoDB 云最低层是免费的,并且可能能够在项目的整个生命周期内处理您的数据量(考虑到您使用的是 rasp pi)。
您可以在 class 变量中累积您的项目,最后将其写入磁盘:
import json
from itemadapter import ItemAdapter
class CustomPipeline:
data = []
def close_spider(self, spider):
# write your self.data to disk here
def process_item(self, item, spider):
self.data.append(ItemAdapter(item).asdict())
return item
对于可能遇到此问题的任何其他人,我在 Whosebug 评论中找到了另一个答案,它监视 items_scraped
信号,允许您根据需要与每个项目进行交互。
所以我的过程是设置每个蜘蛛爬行,然后将每个蜘蛛的结果添加到列表中,并在蜘蛛完成后将其返回到我的进程队列中。
results = []
# Method called every time item_passed signal is received
def crawler_results(signal, sender, item, response, spider):
results.append(item)
# Connect to item_passed signal
dispatcher.connect(crawler_results, signal=signals.item_scraped)
# Initialise a crawler
crawl_process = CrawlerProcess(project.get_project_settings())
# Locate and iterate through the spiders
for spider in (x for x in crawl_process.spider_loader.list()):
crawl_process.crawl(spider)
# Kick it off
crawl_process.start()
# Output results to queue
queue.put(results)
我是 Scrapy 的新手,正在尝试了解我如何输出数据 post-抓取。我已经阅读了一些文档,但我很难理解它,而且可用的文档对于我的用例来说有点模糊。
基本上,我同时启动了大约九个蜘蛛,以从给定网站上抓取某些信息。我按如下方式启动抓取:
from scrapy.utils import project
from scrapy.crawler import CrawlerProcess
# Initialise a crawler
crawl_process = CrawlerProcess(project.get_project_settings())
# Locate and iterate through the spiders
for spider in (x for x in crawl_process.spider_loader.list()):
crawl_process.crawl(spider)
# Kick it off
crawl_process.start()
这些蜘蛛的输出是每个蜘蛛的一个字典(如果有匹配),类似于以下内容:
yield {
'Retailer': 'Amazon',
'Item': 'Product Example',
'Price': '£62.50',
'URL': 'URL'
}
我想尽可能避免写入磁盘,因为这个脚本将 运行 在我的 Raspberry Pi 的 SD 卡上,所以每两个一次写入数十个文件大约几分钟并不理想。
我的要求:
我希望能够找到一种方法来收集内存中的数据,直到所有的蜘蛛都完成,然后我需要能够创建一个字典列表进行比较,最后输出到一个单一的json 文件。这是可能吗?真是摸不着头脑。
如果不可能,我真的很想知道如何正确处理它。
利用 Scrapy Pipeline + MongoDB Cloud 是一个很好的选择。将流水线用于任何逻辑,并将您需要的内容写入 MongoDB.
您也可以只将所有内容添加到 MongoDB 并使用 Pymongo 和一些简单的脚本编写所有逻辑。
选项 2 的管道类似于:
import pymongo
from itemadapter import ItemAdapter
class MongoPipeline:
collection_name = 'scrapy_items'
def open_spider(self, spider):
self.client = pymongo.MongoClient(os.environ.get("MONGO_DB_CONNECTION_STRING"))
self.db = self.client["db name"]
def close_spider(self, spider):
self.client.close()
def process_item(self, item, spider):
self.db[self.collection_name].insert_one(ItemAdapter(item).asdict())
return item
MongoDB 云最低层是免费的,并且可能能够在项目的整个生命周期内处理您的数据量(考虑到您使用的是 rasp pi)。
您可以在 class 变量中累积您的项目,最后将其写入磁盘:
import json
from itemadapter import ItemAdapter
class CustomPipeline:
data = []
def close_spider(self, spider):
# write your self.data to disk here
def process_item(self, item, spider):
self.data.append(ItemAdapter(item).asdict())
return item
对于可能遇到此问题的任何其他人,我在 Whosebug 评论中找到了另一个答案,它监视 items_scraped
信号,允许您根据需要与每个项目进行交互。
所以我的过程是设置每个蜘蛛爬行,然后将每个蜘蛛的结果添加到列表中,并在蜘蛛完成后将其返回到我的进程队列中。
results = []
# Method called every time item_passed signal is received
def crawler_results(signal, sender, item, response, spider):
results.append(item)
# Connect to item_passed signal
dispatcher.connect(crawler_results, signal=signals.item_scraped)
# Initialise a crawler
crawl_process = CrawlerProcess(project.get_project_settings())
# Locate and iterate through the spiders
for spider in (x for x in crawl_process.spider_loader.list()):
crawl_process.crawl(spider)
# Kick it off
crawl_process.start()
# Output results to queue
queue.put(results)