#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
Ответ №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 элементов вместо одного. Оттуда вы выполняете итерацию по каждому узлу и извлекаете нужные вам данные. Предложение для чтения .