class MySiteSpider(scrapy.Spider):
name = 'MySite'
allowed_domains = ['example.com']
start_urls = ['http://example.com/']
def parse(self, response):
links = LinkExtractor(unique=True).extract_links(response)
for link in links:
yield response.follow(link, callback=self.parse)
pass
if response.css('.product-page-content'):
id_ = response.css('#id::text').extract_first()
item = MyItem()
item['id'] = id
item['urls'] = [response.url]
# Sorting some data
yield item
问题是,有时我得到的页面具有不同的url
但具有相同的id_
,在这种情况下,我需要将此新url添加到具有旧id_
/的旧项目中喜欢:
if response.css('.product-page-content'):
id_ = response.css('#id::text').extract_first()
if this_id_already_processed:
old_item['url'].append(response.url)
else
item = MyItem()
item['id'] = id
item['urls'] = [response.url]
# Sorting some data
yield item
答案 0 :(得分:3)
有趣的情况。有几种方法可以做到,但这种情况下的主要障碍是记忆。
当scrapy产生一个项目时,它将其导出到您具有的任何输出(stdout,json,csv等),然后就完成了。 如果您希望通过这种方式合并项目,则需要对输出进行后处理或将所有内容保存到内存中。
后处理输出
如果您在output.csv
中有文件,则可以简单地对结果运行脚本以加入您的项目。看到spider_closed信号-蜘蛛关闭时打开ouput.json
并调整内容
管道
通过这种方法,您可以将所有项目存储在内存中,并在爬网程序运行时对其进行处理:
import json
class MyPipeline:
items = {}
def process_item(self, item):
if item['id'] in self.items:
self.items['id']['urls'].append(item['url'])
else:
self.items[item['id']] = item
return item
close_spider(self, spider):
with open('output.json') as f:
f.write(json.dumps(self.items))
饲料出口商
这几乎与管道方法相同-在导出之前将项目保存到内存中
如果您的Spider很小,请选择#2,否则,#1是一种内存效率更高,更清洁的方法。
答案 1 :(得分:-1)
由于Scrapy的工作原理,因此无法以简单的方式执行此操作。它异步处理请求,一个接一个地产生项目,它本身不维护任何历史记录。您可以做的是在蜘蛛网中使用一些项目缓冲区,并在抓取结束时使用signals转储所有项目。
请参见以下虚拟示例:
import json
import scrapy
from scrapy import signals
class QuotesSpider(scrapy.Spider):
name = 'quotes'
start_urls = ['http://quotes.toscrape.com/page/1/']
items = []
@classmethod
def from_crawler(cls, crawler, *args, **kwargs):
spider = super(QuotesSpider, cls).from_crawler(crawler, *args, **kwargs)
crawler.signals.connect(spider.spider_closed, signal=signals.spider_closed)
return spider
def parse(self, response):
for quote in response.xpath('//div[@class="quote"]'):
item = {
'text': quote.xpath('normalize-space(./span[@class="text"])').extract_first()
}
self.items.append(item)
def spider_closed(self, spider):
with open('items.json', 'wt') as f:
json.dump(self.items, f)