Ich habe Spinne, die Anfragen in Kette mit meta
verarbeitet, um Elemente, die Daten aus mehreren Anforderungen haben. Die Art und Weise, wie ich Anfragen generierte, ist die Initiierung aller Anfragen beim ersten Aufruf der Parse-Funktion. Wenn ich zu viele Links zur Anfrage habe, werden nicht alle eingeplant und ich bekomme am Ende nicht alles, was ich brauche.Scrapy Spider nicht Spider_idle Signal
Um das zu beheben, versuche ich, die Spinne anzufordern, 5 Produkte zu einem Zeitpunkt anzufordern, wieder anfordert, wenn die Spinne im Leerlauf ist (durch Anschließen eines Signals in from_crawler
). Das Problem ist, dass, wie mein Code gerade jetzt ist, spider_idle nicht die request
Funktion ausführt und der Spider schließt sofort. Es ist, als ob die Spinne nicht untätig ist.
Hier ist ein Teil des Codes:
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
In Ordnung! Danke, es scheint zu funktionieren :) Was ist der Unterschied zwischen einer normalen scrapy.Request() und self.crawler.engine.crawl? – AimiHat
Es gibt keinen wirklichen Unterschied, die einzige Sache ist, dass 'scrapy' die Callback-Methoden handhabt, die sie der Requests-Queue hinzufügen, ohne dass Sie es bemerken, und mit' self.crawler.engine..' fügen Sie die Anfragen explizit hinzu – eLRuLL