Разница между get() и getall() в Scrapy и интерпретация вывода кода

#python #json #parsing #web-scraping #scrapy

#python #json #синтаксический анализ #веб-очистка #scrapy

Вопрос:

Кто-нибудь может мне здесь помочь?

У меня есть этот код, но когда я использую get() его, он просто фиксирует первые продукты каждой страницы, и файл JSON поступает так, как я хочу. Когда я использую getall() , он принимает все необходимые мне продукты, но файл JSON отличается.

Например, у меня есть 50 страниц и 50 продуктов на страницу, в общей сложности 2500 продуктов. В get() методе требуется всего 50, в getall() методе требуется все, но со странным файлом JSON.

Я хочу тот же вывод JSON get() , что и метод, но захват всех продуктов точно getall() так же, как метод

Я приложу код и распечатки файлов JSON

 # -*- coding: utf-8 -*-

import scrapy
from scrapy.exceptions import CloseSpider


class ProdutosSpider(scrapy.Spider):
    name = 'produtos'
    allowed_domains = ['www.allpartsnet.com.br']
    start_urls = [
        "https://www.allpartsnet.com.br/buscapagina?fq=B:1228amp;O=OrderByNameASCamp;PS=50amp;sl=5d58b484-137e-4091-92ca-29d2e0c70f85amp;cc=1amp;sm=0amp;PageNumber=0"]
    page = 0

    def parse(self, response):

        if len(response.xpath("//*[@class='QD prateleira row qd-xs n1colunas']")) == 0:
            raise CloseSpider('No more products to scrape...')

        for produtos in response.xpath("//*[@class='QD prateleira row qd-xs n1colunas']"):
            yield {
                'nome': produtos.xpath("//*[@class='shelf-product-name ']/a/@title").getall(),
                'url': produtos.xpath("//*[@class='shelf-product-name ']/a/@href").getall(),
                'valor': produtos.xpath("//*[@class='old-price']/text()").getall(),
                'valor_desc': produtos.xpath("//*[@class='best-price']/text()").getall()
            }

        self.page  = 1
        yield scrapy.Request(
            url=f'https://www.allpartsnet.com.br/buscapagina?fq=B:1228amp;O=OrderByNameASCamp;PS=50amp;sl=5d58b484-137e-4091-92ca-29d2e0c70f85amp;cc=1amp;sm=0amp;PageNumber={self.page}',
            callback=self.parse
        )
  

get()

https://i.imgur.com/9GzFoJn.png

ALT SHIFT F

https://i.imgur.com/GyvfqNB.png

getall()

https://i.imgur.com/JJsEEey.png

ALT SHIFT F

https://i.imgur.com/2UlenWI.png

Ответ №1:

Метод .get() всегда будет возвращать первый элемент, найденный вашим селектором, в виде строки.

Метод .getall() всегда будет возвращать список строк со ВСЕМИ элементами, найденными вашим селектором.

Подробнее здесь

Я хочу тот же вывод JSON, что и метод get (), но захват всех продуктов точно так же, как метод getall ()

Мне кажется, что проблема, с которой вы столкнулись, связана не с get()/getall() методом, а с XPath. Вы должны заменить строки produtos.xpath("...").getall() на produtos.xpath("...").get() , поскольку вы выполняете итерацию между всеми селекторами produtos .

Однако, когда вы используете селектор, подобный этому:

 "//*[@class='shelf-product-name ']/a/@title"
  

вы вызываете ось descendant-or-self ( // ) для всего документа, а не в контексте текущего узла ( .// ) .

Попробуйте это и дайте мне знать, помогло ли это:

    for produtos in response.xpath("//*[@class='QD prateleira row qd-xs n1colunas']"):
        yield {
            'nome': produtos.xpath(".//*[@class='shelf-product-name ']/a/@title").get(),
            'url': produtos.xpath(".//*[@class='shelf-product-name ']/a/@href").get(),
            'valor': produtos.xpath(".//*[@class='old-price']/text()").get(),
            'valor_desc': produtos.xpath(".//*[@class='best-price']/text()").get()
        }
  

PS.: В будущем, пожалуйста, не используйте изображения для отображения вашего кода / вывода / журналов, всегда копируйте и вставляйте его фрагмент в вопрос

Редактировать:

Извините, я на самом деле не проверял страницу раньше. Проблема по-прежнему связана с Xpath. Этот селектор выбирает один элемент:

 for produtos in response.xpath("//*[@class='QD prateleira row qd-xs n1colunas']"):
  

Таким образом, вы на самом деле ничего не перебираете, поскольку есть один возврат. Попробуйте заменить его на

 for produtos in response.xpath("//*[@class='QD prateleira row qd-xs n1colunas']/ul/li[not(@class='helperComplement')]"):
  

в дополнение к предложениям, которые я упоминал ранее.

Комментарии:

1. Спасибо @renatodvc, теперь это сработало. Я не знаю, хорошо ли я это понял, но мне нужно было уточнить xpath? Еще раз спасибо! Мне очень помогло!

2. Рад слышать Лукаса. Ваш XPath выбирал один элемент [parent], но вы хотите выполнить итерацию между строками (элементов), поэтому селектор должен указывать на строки. Тот, который я предлагаю, возвращает 50 элементов вместо одного. Оттуда вы выполняете итерацию по каждому узлу и извлекаете нужные вам данные. Предложение для чтения .