В 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'])
Другие вопросы по тегам