Scrapy - не может сделать несколько обратных вызовов - PullRequest
0 голосов
/ 28 февраля 2020

У меня проблемы с просмотром нескольких страниц. Вот мой класс для кода под названием quotes.

class quotes(scrapy.Spider):
    name = 'quotes'
    start_urls = ['http://books.toscrape.com/?']

def parse(self, response):
    all_links = response.css('.nav-list ul li')
    for links in all_links:
        link = links.css('a::attr(href)').get()
        yield response.follow(link, callback = self.books_detail)

def books_detail(self, response):
    yas = {
    'title':[],
    'price':[],
    'availability':[],
    'category':[]
    }
    yas['category'].append(response.css('h1::text').extract())
    all_divs = response.css('.col-lg-3')
    for div in all_divs:
        link = div.css('.product_pod a::attr(href)').get()
        title = response.follow(link, callback = self.get_title)

        yas['price'].append(div.css('.price_color::text').extract())
        yas['availability'].append(div.css('.availability::text')[1].extract())
    yield yas


def get_title(self,response):   
    print('testing')
    title = response.css('h1::text').extract()
    yield {"title":title}

Поэтому я использую response.follow для перехода к функции books_details , и в этой функции я снова вызываю response.follow для вызова get_title . Я получаю название из get_title, а остальные детали с главной страницы. Я могу просто получить информацию из функции books_details , а также получить ссылку на титульную страницу также из строки кода.

link = div.css('.product_pod a::attr(href)').get()

Но используя response.follow Я не могу go к функции get_title. Любая помощь будет оценена. Спасибо.

1 Ответ

1 голос
/ 28 февраля 2020

Вы должны выдать запрос, не запускать его напрямую и использовать meta= для отправки данных в следующий анализатор

yield response.follow(link, callback=self.get_title, meta={'item': yas})

, а в следующем анализаторе вы можете получить его

yas = response.meta['item']

а затем вы можете добавить новые значения и получить все данные

yas["title"] = response.css('h1::text').extract()

yield yas

См. другой пример в Scrap получить элементы из нескольких запросов

Do c: Запрос и ответ , Специальные ключи Request.meta


Минимальный рабочий код , который можно поместить в один файл и запустить как обычно скрипт (python script.py) без создания проекта.

Есть и другие изменения.

Не следует складывать все книги в один список, а отдавать каждую книгу отдельно. Scrapy сохранит все результаты, и когда вы используете опцию для сохранения в csv, он сохранит все результаты.

Для каждой книги вы должны создать новый словарь. Если вы используете один и тот же словарь много раз, он перезапишет данные, и вы можете получить много результатов с одними и теми же данными.

import scrapy

class QuotesSpider(scrapy.Spider):

    name = 'quotes'

    start_urls = ['http://books.toscrape.com/']

    def parse(self, response):
        all_links = response.css('.nav-list ul li')
        for links in all_links:
            link = links.css('a::attr(href)').get()
            yield response.follow(link, callback=self.books_detail)


    def books_detail(self, response):

        all_divs = response.css('.col-lg-3')

        for div in all_divs:
            # every book in separated dictionary and it has to be new dictionary - because it could overwrite old data
            book = {
                'category': response.css('h1::text').extract(),
                'price': div.css('.price_color::text').extract()[0].strip(),
                'availability': div.css('.availability::text')[1].extract().strip(),
            }

            link = div.css('.product_pod a::attr(href)').get()
            yield response.follow(link, callback=self.get_title, meta={'item': book})


    def get_title(self, response):
        book = response.meta['item']

        print('testing:', response.url)

        book["title"] = response.css('h1::text').extract()[0].strip() 

        yield book

# --- run without project and save in `output.csv` ---

from scrapy.crawler import CrawlerProcess

c = CrawlerProcess({
    'USER_AGENT': 'Mozilla/5.0',
    # save in file CSV, JSON or XML
    'FEED_FORMAT': 'csv',     # csv, json, xml
    'FEED_URI': 'output.csv', #
})

c.crawl(QuotesSpider)
c.start()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...