Запрос Scrapy не перезванивает

python web-scraping request scrapy scrapy-spider

1280 просмотра

1 ответ

133 Репутация автора

Я пытаюсь создать паука, который получает данные из CSV (две ссылки и имя в строке) и удаляет простой элемент (цена) из каждой из этих ссылок, возвращая элемент для каждой строки, причем имя элемента является имя в csv и две соскребенные цены (по одной от каждой ссылки).

Все работает, как и ожидалось, за исключением того факта, что вместо того, чтобы возвращать цены, которые будут возвращаться из функции обратного вызова каждого запроса, я получаю объект запроса следующим образом:

https://link.com > ..

Функции обратного вызова вообще не вызываются, почему это так?

Вот паук:

f = open('data.csv')
f_reader = csv.reader(f)
f_data = list(f_reader)

parsed_data = []

for product in f_data:
    product = product[0].split(';')
    parsed_data.append(product)

f.close()

class ProductSpider(scrapy.Spider):
    name = 'products'
    allowed_domains = ['domain1', 'domain2']

    start_urls = ["domain1_but_its_fairly_useless"]

    def parse(self, response):
        global parsed_data
        for product in parsed_data:

            item = Product()

            item['name'] = product[0]
            item['first_price'] = scrapy.Request(product[1], callback=self.parse_first)
            item['second_price'] = scrapy.Request(product[2], callback=self.parse_second)
            yield item


    def parse_first(self, response):
        digits = response.css('.price_info .price span').extract()
        decimals = response.css('.price_info .price .price_demicals').extract()
        yield float(str(digits)+'.'+str(decimals))

    def parse_second(self, response):
        digits = response.css('.lr-prod-pricebox-price .lr-prod-pricebox-price-primary span[itemprop="price"]').extract()
        yield digits

Заранее спасибо за вашу помощь!

Автор: AimiHat Источник Размещён: 18.07.2016 04:50

Ответы (1)


3 плюса

13488 Репутация автора

Решение

TL; DR: Вы получаете предмет с объектами Request внутри него, когда вы должны получить либо Item, либо Request.


Длинная версия:
методы анализа в вашем пауке должны либо возвращать a scrapy.Item- в этом случае цепочка для этого сканирования будет остановлена, и scrapy выдает элемент, либо scrapy.Requestsв этом случае scrapy будет планировать запрос на продолжение цепочки.

Scrapy является асинхронным, поэтому создание элемента из нескольких запросов означает, что вам нужно объединить все эти запросы, перенося ваш элемент к каждому элементу, и постепенно заполнять его. Объект запроса имеет metaатрибут, в котором вы можете хранить все, что захотите (в значительной степени), и он будет перенесен в вашу функцию обратного вызова. Очень часто его используют для объединения запросов для элементов, которые требуют нескольких запросов для формирования одного элемента.

Ваш паук должен выглядеть примерно так:

class ProductSpider(scrapy.Spider):
    # <...>
    def parse(self, response):
        for product in parsed_data:
            item = Product()
            item['name'] = product[0]
            # carry next url you want to crawl in meta
            # and carry your item in meta
            yield Request(product[1], self.parse_first,
                          meta={"product3": product[2], "item":item})  


    def parse_first(self, response):
        # retrieve your item that you made in parse() func
        item = response.meta['item']
        # fill it up
        digits = response.css('.price_info .price span').extract()
        decimals = response.css('.price_info .price .price_demicals').extract()
        item['first_price'] = float(str(digits)+'.'+str(decimals))
        # retrieve next url from meta
        # carry over your item to the next url
        yield Request(response.meta['product3'], self.parse_second,
                      meta={"item":item})


    def parse_second(self, response):
        # again, retrieve your item
        item = response.meta['item']
        # fill it up
        digits = response.css('.lr-prod-pricebox-price .lr-prod-pricebox-price-primary 
                              span[itemprop="price"]').extract()
        item['secodn_price'] = digits
        # and finally return the item after 3 requests! 
        yield item
Автор: Granitosaurus Размещён: 18.07.2016 05:05
Вопросы из категории :
32x32