В Scrapy, как передать URL-адреса, сгенерированные в одном классе, следующему классу в сценарии?
Ниже приведен код моего паука:
import scrapy
class ProductMainPageSpider(scrapy.Spider):
name = 'ProductMainPageSpider'
start_urls = ['http://domain.com/main-product-page']
def parse(self, response):
for product in response.css('article.isotopeItem'):
yield {
'title': product.css('h3 a::text').extract_first().encode("utf-8"),
'category': product.css('h6 a::text').extract_first(),
'img': product.css('figure a img::attr("src")').extract_first(),
'url': product.css('h3 a::attr("href")').extract_first()
}
class ProductSecondaryPageSpider(scrapy.Spider):
name = 'ProductSecondaryPageSpider'
start_urls = """ URLS IN product['url'] FROM PREVIOUS CLASS """
def parse(self, response):
for product in response.css('article.isotopeItem'):
yield {
'title': product.css('h3 a::text').extract_first().encode("utf-8"),
'thumbnail': product.css('figure a img::attr("src")').extract_first(),
'short_description': product.css('div.summary').extract_first(),
'description': product.css('div.description').extract_first(),
'gallery_images': product.css('figure a img.gallery-item ::attr("src")').extract_first()
}
Первый класс / часть работает правильно, если я удаляю второй класс / часть. Он генерирует мой файл JSON правильно с элементами, запрошенными в нем. Тем не менее, сайт, который мне нужно сканировать, состоит из двух частей. Он имеет страницу архива товара, которая показывает товары в виде эскиза, заголовка и категории (и этой информации нет на следующей странице). Затем, если вы нажмете на одну из миниатюр или заголовков, вы попадете на одну страницу продукта, где есть конкретная информация о продукте.
Продуктов много, поэтому я бы хотел перенаправить (yield?) URL-адреса в product['url'] во второй класс в виде списка "start_urls". Но я просто не знаю, как это сделать. Мои знания не зашли достаточно далеко, чтобы даже понять, что мне не хватает или что идет не так, чтобы я мог найти решение.
Проверьте в строке 20, что я хочу сделать.
1 ответ
Вам не нужно создавать двух пауков для этого - вы можете просто перейти к следующему URL и перенести ваш предмет, т.е.
def parse(self, response):
item = MyItem()
item['name'] = response.xpath("//name/text()").extract()
next_page_url = response.xpath("//a[@class='next']/@href").extract_first()
yield Request(next_page_url,
self.parse_next,
meta={'item': item} # carry over our item
)
def parse_next(self, response):
# get our carried item from response meta
item = response.meta['item']
item['description'] = response.xpath("//description/text()").extract()
yield item
Однако, если по какой-то причине вы действительно хотите разделить логику этих двух шагов, вы можете просто сохранить результаты в файле (например, json: scrapy crawl first_spider -o results.json
) и открыть / перебрать его во втором пауке в start_requests()
метод класса, который выдает URL, т.е.
import json
from scrapy import spider
class MySecondSpider(spider):
def start_requests(self):
# this overrides `start_urls` logic
with open('results.json', 'r') as f:
data = json.loads(f.read())
for item in data:
yield Request(item['url'])