Как заставить scrapy обрабатывать одну группу/список URL-адресов за другой? У меня есть два списка URL-адресов. Мне нужно обработать первый список, включая item pipelines, а затем я могу обработать второй список.
Оба должны быть обработаны одним пауком.
Я не уверен, что priority поможет мне.
priority (int) – приоритет данного запроса (по умолчанию 0). Приоритет используется планировщиком для определения порядка обработки запросов. Запросы с более высоким значением приоритета будут выполняться раньше. Отрицательные значения допускаются для обозначения относительно низкого приоритета.
Потому что я не знаю, просто ли он переупорядочивает Requests в соответствии с приоритетом - это может закончиться конвейерным преобразованием первых URL-адресов из второго списка перед последними URL-адресами из первого списка.
Могу ли я быть уверен, что items из первого списка будут экспортированы в XML (я использую XMLItemExporter) раньше, чем из второго списка?
РЕДАКТИРОВАТЬ:
ОШИБКА (@Wilfredo):
2017-11-23 20:12:16 [scrapy.utils.signal] ОШИБКА: ошибка обнаружена в обработчике сигнала: > Traceback (последний последний вызов): файл "/home/milano/.virtualenvs/eoilenv/local/lib/ python2.7/site-packages/scrapy/utils/signal.py", строка 30, в send_catch_log *arguments, **named) File "/home/milano/.virtualenvs/eoilenv/local/lib/python2.7/site -packages/pydispatch/robustapply.py", строка 55, в робастаппли возвращаем получатель (*аргументы, **имя) TypeError: spider_idle() принимает ровно 2 аргумента (1 указан) 2017-11-23 20:12:16 [scrapy .core.engine] ИНФОРМАЦИЯ: закрывающий паук (готово)
РЕДАКЦИЯ II:
# coding=utf-8
import scrapy
from bot.items import TestItem
from scrapy import Spider, Request, signals
from scrapy.exceptions import DontCloseSpider
class IndexSpider(Spider):
name = 'index_spider'
allowed_domains = ['www.scrape.com']
def start_requests(self):
for url in ["https://www.scrape.com/eshop"]:
# for url in ["https://www.scrape.com/search/getAjaxResult?categoryId=1&"]:
yield Request(url, callback=self.parse_main_page)
def parse_main_page(self, response):
# get subcategories and categories
self.categories = []
self.subcategories = []
parts = response.selector.xpath("//div[contains(@class,'side-nav') and not(contains(@class,'side-nav-'))]")
for part in parts:
part_name = part.xpath('.//h4/text()').extract_first().strip()
category_list = [part_name]
categories_ul = part.xpath('./ul')
categories_lis = categories_ul.xpath('./li')
for category_li in categories_lis:
category_list = category_list[:1]
category_name = category_li.xpath('./a/text()').extract_first().strip()
category_href = category_li.xpath('./a/@href').extract_first().strip()
categoryId = self._extract_categoryId_from_url(category_href)
category_list.append(category_name)
self.categories.append((categoryId, category_list))
subcategories_lis = category_li.xpath('.//li')
for subcategory_li in subcategories_lis:
category_list = category_list[:2]
subcategory_href = subcategory_li.xpath('./a/@href').extract_first()
subcategory_name = subcategory_li.xpath('./a/text()').extract_first().strip()
subcategoryId = self._extract_categoryId_from_url(subcategory_href)
category_list.append(subcategory_name)
self.subcategories.append((subcategoryId, category_list))
# Scrape all subcategories (then categories)
# for sub in self.subcategories:
# url = "https://www.scrape.com/search/getAjaxResult?categoryId={}".format(sub[0])
# yield Request(url,meta={'tup':sub,'priority':1,'type':'subcategory'},priority=1,callback=self.parse_category)
def parse_category(self, response):
tup = response.meta['tup']
type = response.meta['type']
priority = response.meta['priority']
current_page = response.meta.get('page', 1)
categoryId = tup[0]
categories_list = tup[1]
number_of_pages_href = response.selector.xpath(u'//a[text()="Last"]/@href').extract_first()
try:
number_of_pages = int(number_of_pages_href.split('p=')[1].split('&')[0])
except:
number_of_pages = current_page
if current_page < number_of_pages:
url = "https://www.scrape.com/search/getAjaxResult/?categoryId={}&p={}".format(categoryId, current_page + 1)
yield Request(url, self.parse_category, meta={'tup': tup, 'page': current_page + 1,'priority':priority,'type':type}, priority=priority)
hrefs = self._extract_all_product_urls(response)
for href in hrefs:
yield Request(href, self.parse_product, meta={"categories_list": categories_list,'type':type}, priority=2 if priority==1 else -1)
def parse_product(self, response):
yield TestItem(url=response.url,type=response.meta['type'], category_text='|'.join(response.meta['categories_list']))
def _extract_categoryId_from_url(self, url):
categoryId = url.split('/')[-2]
return categoryId
def _extract_all_product_urls(self, response):
hrefs = response.selector.xpath("//a[contains(@class, 'shop-item-image')]/@href").extract()
return [u"https://www.scrape.com{}".format(x) for x in hrefs]
@classmethod
def from_crawler(cls, crawler, *args, **kwargs):
spider = super(IndexSpider, cls).from_crawler(crawler, *args, **kwargs)
crawler.signals.connect(spider.spider_idle,
signal=scrapy.signals.spider_idle)
return spider
def spider_idle(self):
self.crawler.signals.disconnect(self.spider_idle,
signal=scrapy.signals.spider_idle)
# yield a new group of urls
if self.categories:
for cat in self.categories:
url = "https://www.scrape.com/search/getAjaxResult?categoryId={}".format(cat[0])
yield Request(url, meta={'tup': cat, 'priority': 0, 'type': 'category'}, priority=0,
callback=self.parse_category)
self.categories = []
raise DontCloseSpider()