Scrapy объединяет связанные запросы в один

У меня есть сценарий, когда я просматриваю магазин, просматривая десятки страниц. Затем, когда я найду нужный товар, я добавлю его в корзину.

Наконец я хочу оформить заказ. Проблема в том, что при цепочке скрапа он хочет проверять корзину столько раз, сколько у меня есть предметов в корзине.

Как объединить связанные запросы в один, чтобы после добавления 10 товаров в корзину оформление заказа вызывалось только один раз?

def start_requests(self):
    params = getShopList()
    for param in params:
        yield scrapy.FormRequest('https://foo.bar/shop', callback=self.addToBasket,
                                 method='POST', formdata=param)


def addToBasket(self, response):
    yield scrapy.FormRequest('https://foo.bar/addToBasket', callback=self.checkoutBasket,
                             method='POST',
                             formdata=param)

def checkoutBasket(self, response):
    yield scrapy.FormRequest('https://foo.bar/checkout', callback=self.final, method='POST',
                             formdata=param)

def final(self):
    print("Success, you have purchased 59 items")

РЕДАКТИРОВАТЬ:

Я пытался сделать запрос в закрытом событии, но он не работает ни на запрос, ни на обратный вызов.

  def closed(self, reason):
        if reason == "finished":
            print("spider finished")
            return scrapy.Request('https://www.google.com', callback=self.finalmethod)
        print("Spider closed but not finished.")

    def finalmethod(self, response):
        print("finalized")

2 ответа

Решение

Я решил это с помощью сигналов Scrapy и spider_idle вызов.

Отправляется, когда паук бездействует, что означает, что у паука больше нет:

  • запросы, ожидающие загрузки
  • Запрашивает
  • обрабатывается в конвейере товаров

https://doc.scrapy.org/en/latest/topics/signals.html

from scrapy import signals, Spider

class MySpider(scrapy.Spider):
    name = 'whatever'

    def start_requests(self):
        self.crawler.signals.connect(self.spider_idle, signals.spider_idle) ## notice this
        params = getShopList()
        for param in params:
            yield scrapy.FormRequest('https://foo.bar/shop', callback=self.addToBasket,
                                     method='POST', formdata=param)


    def addToBasket(self, response):
        yield scrapy.FormRequest('https://foo.bar/addToBasket',
                                 method='POST', formdata=param)

    def spider_idle(self, spider): ## when all requests are finished, this is called
        req = scrapy.Request('https://foo.bar/checkout', callback=self.checkoutFinished)
        self.crawler.engine.crawl(req, spider)

    def checkoutFinished(self, response):
        print("Checkout finished")

Я думаю, что вы можете вручную оформить заказ, когда паук закончил:

def closed(self, reason):
    if reason == "finished":
        return requests.post(checkout_url, data=param)
    print("Spider closed but not finished.")

Смотри закрыто.

Обновить

class MySpider(scrapy.Spider):
    name = 'whatever'

    def start_requests(self):
        params = getShopList()
        for param in params:
            yield scrapy.FormRequest('https://foo.bar/shop', callback=self.addToBasket,
                                     method='POST', formdata=param)


    def addToBasket(self, response):
        yield scrapy.FormRequest('https://foo.bar/addToBasket',
                                 method='POST', formdata=param)

    def closed(self, reason):
        if reason == "finished":
            return requests.post(checkout_url, data=param)
        print("Spider closed but not finished.")
Другие вопросы по тегам