【问题标题】:How can I avoid that an array is resetting after a callback?如何避免数组在回调后重置?
【发布时间】:2017-11-08 16:45:05
【问题描述】:

我想使用 scrapy 从网站上抓取评论数据。代码如下。

问题是每次程序进入下一页时,它都会从头开始(由于回调)并重置records[]。因此数组将再次为空,并且保存在records[] 中的每条评论都将丢失。这导致当我打开我的 csv 文件时,我只得到最后一页的评论。

我想要的是所有数据都存储在我的 csv 文件中,这样records[] 就不会在每次请求下一页时都重新设置。我不能在 parse 方法之前放行:records = [],因为没有定义数组。

这是我的代码:

def parse(self, response):
    records = []

    for r in response.xpath('//div[contains(@class, "a-section review")]'):
        rtext = r.xpath('.//div[contains(@class, "a-row review-data")]').extract_first()                
        rating = r.xpath('.//span[contains(@class, "a-icon-alt")]/text()').extract_first()
        votes = r.xpath('normalize-space(.//span[contains(@class, "review-votes")]/text())').extract_first()

        if not votes:
            votes = "none"

        records.append((rating, votes, rtext))
        print(records)

    nextPage = response.xpath('//li[contains(@class, "a-last")]/a/@href').extract_first()
    if nextPage:
        nextPage = response.urljoin(nextPage)
        yield scrapy.Request(url = nextPage)    

    import pandas as pd
    df = pd.DataFrame(records, columns=['rating' , 'votes', 'rtext'])
    df.to_csv('ama.csv', sep = '|', index =False, encoding='utf-8')

【问题讨论】:

    标签: python csv callback scrapy


    【解决方案1】:

    将记录声明移动到方法调用将使用 python 中概述的常见问题here in the python docs。然而,在这种情况下,在方法声明中实例化列表的奇怪行为将对您有利。

    Python 的默认参数在定义函数时计算一次,而不是每次调用函数时(就像在 Ruby 中一样)。这意味着,如果您使用可变的默认参数并对其进行变异,那么您将并且已经对该对象进行了变异,以便将来调用该函数。

    def parse(self, response, records=[]):
    
    
        for r in response.xpath('//div[contains(@class, "a-section review")]'):
            rtext = r.xpath('.//div[contains(@class, "a-row review-data")]').extract_first()                
            rating = r.xpath('.//span[contains(@class, "a-icon-alt")]/text()').extract_first()
            votes = r.xpath('normalize-space(.//span[contains(@class, "review-votes")]/text())').extract_first()
    
            if not votes:
                votes = "none"
    
            records.append((rating, votes, rtext))
            print(records)
    
        nextPage = response.xpath('//li[contains(@class, "a-last")]/a/@href').extract_first()
        if nextPage:
            nextPage = response.urljoin(nextPage)
            yield scrapy.Request(url = nextPage)    
    
        import pandas as pd
        df = pd.DataFrame(records, columns=['rating' , 'votes', 'rtext'])
        df.to_csv('ama.csv', sep = '|', index =False, encoding='utf-8')
    

    上面的方法有点奇怪。更通用的解决方案是简单地使用全局变量。 Here is a post going over how to use globals.

    【讨论】:

      【解决方案2】:

      这里的parse 是一个回调,每次都会再次调用。尝试全局定义records 或调用appender 函数并调用它来追加值。

      scrappy 也能够自己生成 CSV。这是我的抓取小实验 - https://gist.github.com/lisitsky/c4aac52edcb7abfd5975be067face1bb

      因此,您可以将数据加载到 csv,然后 pandas 会读取它。

      【讨论】:

      • 谢谢 :D 这也是正确的,但上面的更具体一点
      猜你喜欢
      • 2022-10-24
      • 1970-01-01
      • 1970-01-01
      • 2018-05-15
      • 1970-01-01
      • 2010-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多