Scrapy蜘蛛没有收到spider_idle信号
问题描述:
我有蜘蛛处理链中的请求使用meta
产生具有来自多个请求的数据的项目。 我用来生成请求的方式是在第一次调用解析函数时启动所有请求,但是,如果我有太多的链接来请求并不是所有的请求都被调度,并且我最终没有得到所需的一切。Scrapy蜘蛛没有收到spider_idle信号
为了解决这个问题,我试图让蜘蛛请求5种产品,当蜘蛛闲置时(通过连接from_crawler
中的信号)再次请求蜘蛛。 问题是,因为我的代码是现在,spider_idle不运行request
函数和蜘蛛立即关闭。就好像蜘蛛不会闲置一样。
下面是一些代码:
class ProductSpider(scrapy.Spider):
def __init__(self, *args, **kwargs):
super(ProductSpider, self).__init__(*args, **kwargs)
self.parsed_data = []
self.header = {}
f = open('file.csv', 'r')
f_data = [[x.strip()] for x in f]
count=1
first = 'smth'
for product in f_data:
if first != '':
header = product[0].split(';')
for each in range(len(header[1:])):
self.header[header[each+1]] = each+1
first = ''
else:
product = product[0].split(';')
product.append(count)
count+=1
self.parsed_data.append(product)
f.close()
@classmethod
def from_crawler(cls, crawler, *args, **kwargs):
spider = super(ProductSpider, cls).from_crawler(crawler, *args, **kwargs)
crawler.signals.connect(spider.request, signal=signals.spider_idle)
return spider
name = 'products'
allowed_domains = [domains]
handle_httpstatus_list = [400, 404, 403, 503, 504]
start_urls = [start]
def next_link(self,response):
product = response.meta['product']
there_is_next = False
for each in range(response.meta['each']+1, len(product)-1):
if product[each] != '':
there_is_next = True
yield scrapy.Request(product[each], callback=response.meta['func_dict'][each], meta={'func_dict': response.meta['func_dict'],'product':product,'each':each,'price_dict':response.meta['price_dict'], 'item':response.meta['item']}, dont_filter=True)
break
if not there_is_next:
item = response.meta['item']
item['prices'] = response.meta['price_dict']
yield item
#[...] chain parsing functions for each request
def get_products(self):
products = []
data = self.parsed_data
for each in range(5):
if data:
products.append(data.pop())
return products
def request(self):
item = Header()
item['first'] = True
item['sellers'] = self.header
yield item
func_dict = {parsing_functions_for_every_site}
products = self.get_products()
if not products:
return
for product in products:
item = Product()
price_dict = {1:product[1]}
item['name'] = product[0]
item['order'] = product[-1]
for each in range(2, len(product)-1):
if product[each] != '':
#print each, func_dict, product[each]
yield scrapy.Request(product[each], callback=func_dict[each],
meta={'func_dict': func_dict,'product':product,
'each':each,'price_dict':price_dict, 'item':item})
break
raise DontCloseSpider
def parse(self, response=None):
pass
答
我假设你已经证明了其为达到您的request
方法和实际的问题是,这个方法不屈服的要求(甚至项) 。
这是在处理Scrapy中的信号时常见的错误,因为关联的方法不能产生项目/请求。绕过这个问题的方法是使用
用于请求:
request = Request('myurl', callback=self.method_to_parse)
self.crawler.engine.crawl(
request,
spider
)
为项:
item = MyItem()
self.crawler.engine.scraper._process_spidermw_output(
item,
None,
Response(''),
spider,
)
此外,spider_idle
信号方法需要接收spider
参数,所以在你的情况应该是这样的:
def request(self, spider):
...
它应该工作,但我会建议一个更好的方法名称。
好吧!谢谢,它似乎工作:)正常的scrapy.Request()和self.crawler.engine.crawl之间有什么区别? – AimiHat
没有真正的区别,唯一的一点是'scrapy'处理回调方法,将它们添加到请求队列中而不会注意到,并且'self.crawler.engine..'你明确地添加请求 – eLRuLL