【问题标题】:Difference between get() and getall() in Scrapy and Interpreting Code OutputScrapy和解释代码输出中get()和getall()的区别
【发布时间】:2021-01-31 17:58:08
【问题描述】:

有人可以帮我吗?

我有这段代码,但是当我使用get() 时,它只会捕获每个页面的第一个产品,并且 JSON 文件会以我想要的方式出现。当我使用getall() 时,它需要我需要的所有产品,但 JSON 文件不同。

例如,我有 50 个页面,每页 50 个产品,总共 2500 个产品。在get() 方法中只需要 50 个,在getall() 方法中需要全部,但是带有一个奇怪的 JSON 文件。

我想要与 get() 方法相同的 JSON 输出,但像 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%3a1228&O=OrderByNameASC&PS=50&sl=5d58b484-137e-4091-92ca-29d2e0c70f85&cc=1&sm=0&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%3a1228&O=OrderByNameASC&PS=50&sl=5d58b484-137e-4091-92ca-29d2e0c70f85&cc=1&sm=0&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

【问题讨论】:

    标签: python json parsing web-scraping scrapy


    【解决方案1】:

    .get() 方法将始终以字符串形式返回选择器找到的第一个项目。

    .getall() 方法将始终返回一个字符串列表,其中包含您的选择器找到的所有项目。

    More here

    我想要与 get() 方法相同的 JSON 输出,但像 getall() 方法一样捕获所有产品

    在我看来,您遇到的问题不在于 get()/getall() 方法,而在于 XPath。您应该将行 produtos.xpath("...").getall() 替换为 produtos.xpath("...").get(),因为您在 produtos 中的所有选择器之间进行迭代。

    但是,当您像这样使用选择器时:

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

    您是在整个文档而不是在当前节点 (.//) 的上下文中调用后代或自我 (//) 轴。

    试试这个,如果有帮助,请告诉我:

       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')]"):
    

    除了我之前提到的建议。

    【讨论】:

    • 感谢@renatodvc 现在它工作了。我不知道我是否理解得很好,但我需要更具体地了解 xpath?再次感谢你!帮了我很多!
    • 很高兴听到卢卡斯的消息。您的 XPath 选择了单个 [父] 元素,但您希望在(项目的)行之间进行迭代,因此选择器必须指向行。我建议的那个返回 50 个项目,而不是一个。从那里你迭代每个节点并提取你需要的数据。一个reading suggestion
    猜你喜欢
    • 2012-02-13
    • 1970-01-01
    • 2011-07-02
    • 1970-01-01
    • 2015-07-13
    • 2015-01-15
    • 1970-01-01
    • 1970-01-01
    • 2017-07-23
    相关资源
    最近更新 更多