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.")