【问题标题】:Scrapy returns results correctly to terminal but only writes first result to .CSVScrapy 将结果正确返回到终端,但仅将第一个结果写入 .CSV
【发布时间】:2021-08-16 13:31:19
【问题描述】:

此蜘蛛抓取通过将 csv 文件中的唯一产品 ID 添加到 URL 并从给定页面抓取数据而形成的串联链接。

使用 -O 命令将结果写入 .CSV 时,仅写入第一个结果。

所有项目都被正确选择和循环,正确的结果显示在终端的输出中,但只有第一个项目被写入 CSV。

你不能在这样的循环中使用 if else 吗? 定义产量时,response.xpath 中的 x 是否需要另一个?

写入路径和输出文件没有错误

我尝试了几种变体并创建了一个 for try 除了每个元素产生但结果是相同的

如果您有任何解决此问题的建议,请告诉我,谢谢

import scrapy
import pandas as pd


def readcsv():
    df = pd.read_csv('tsuji2.csv')
    #return df.values
    return df['URL'].values.tolist()


class TsujijsonSpider(scrapy.Spider):
    name = 'tsujijson22'
    start_urls = ['https://www.example.co.jp/store/online/']


def parse(self, response):
    for URL in readcsv():



        base_url = 'https://www.example.co.jp/store/online/p/{}'
        yield scrapy.Request(base_url.format(URL), callback=self.data)


def data(self, response):

        try:
            if response.xpath(u"//span[contains(text(), '〇')]").get():
                yield{
                'zaiko green' : response.css('span.green::text').get()}

            elif response.xpath(u"//span[contains(text(), '△')]").get():
                yield{
                    'zaiko red': response.css('span.red:nth-of-type(1)::text').get()}

            else: yield {
                'zaiko red2': response.css('span.upperRight::text').get()}



        except:
            pass

【问题讨论】:

    标签: python scrapy export-to-csv


    【解决方案1】:

    也许您必须在命令末尾键入 -t csv,例如:

    scrapy crawl my_spider -o my_csv_file.csv -t csv
    

    另外,我不知道它是否适合你,但我通常将我的结果写在 json line 文件中 - 每行代表一个 json。

    我在终端上输入这个:

    scrapy crawl my_spider -o my_json_line_file.jl
    

    有一点很重要,那就是你的蜘蛛所在的文件夹。例如,在运行我上面写的命令之前,我输入:

    cd my_project_folder/my_project_folder/spiders
    

    希望对你有帮助! :)

    更新

    我尝试运行几乎相同的代码(仅更改 URL 列表来源)并且它有效。这是我正在使用的代码:

    import scrapy
    
    class MatsukiyoSpider(scrapy.Spider):
        name = 'matsukiyo'
        start_urls = ['https://www.matsukiyo.co.jp/store/online/']
    
        def parse(self, response):
            for URL in ["4582352470220", "4901061475737", "4901061475942"]:
                base_url = 'https://www.matsukiyo.co.jp/store/online/p/{}'
                yield scrapy.Request(base_url.format(URL), callback=self.data)
    
        def data(self, response):
                try:
                    if response.xpath(u"//span[contains(text(), '〇')]").get():
                        yield{
                        'zaiko green' : response.css('span.green::text').get()}
    
                    elif response.xpath(u"//span[contains(text(), '△')]").get():
                        yield{
                            'zaiko red': response.css('span.red:nth-of-type(1)::text').get()}
    
                    else: yield {
                        'zaiko red2': response.css('span.upperRight::text').get()}
    
                except:
                    pass
    

    这是我的 CSV 文件:

    CSV result with only 3 URLs

    PS:我在终端输入了以下内容:

    scrapy crawl matsukiyo -s LOG_LEVEL=DEBUG -o mats.csv -t csv

    【讨论】:

    • 感谢您的建议,但问题仍然存在,不幸的是我需要将文件输出为 CSV
    • 您是否尝试过使用制表符分隔符打开 CSV?我在我的机器上尝试了相同的代码(仅使用 3 个 URL)并且它有效:( - 我用我使用的代码更新了我的答案)。
    • 感谢您的更新,非常感谢您仍在帮助我解决此问题,但是当有多个结果时会出现问题,例如您的代码运行良好,因为所有结果都是〇如果您使用包含△或这两个字符都不包含的不同产品页面,则仅记录第一个和后续值。在你的结果中,所有项目都是〇并且记录正确,如果是〇 -> △ -> △ -> 无〇只会记录第一个〇(即使终端中显示正确,经过测试,我已经意识到问题,我会在下面再次发布。
    • 问题是你不能使用几个不同的列标题 'zaiko green' 'zaiko red' 'zaiko red2' 导致问题,它会找到任何结果=第一个结果,在这种情况下'zaiko green' 然后,scrapy 找到下一个结果,需要写入 'zaiko red' 但列标题已经填充了 'zaiko green',因此返回 null(输入一个空白行)为了规避这个所有列标题必须看起来一样,也许这是 Scrapy 的一个怪癖,或者你必须以某种方式定义一个新列。
    • Marina Rocha Guimarães,感谢您的帮助,让某人检查代码并从不同的角度看待它帮助解决了这个问题,我希望您可以从这里帮助这个网站上的更多人上
    【解决方案2】:

    似乎所有结果都必须具有相同的列标题名称才能正确写入 CSV

    def data(self, response):
            try:
                if response.xpath(u"//span[contains(text(), '〇')]").get():
                    yield{
                    'zaiko' : response.css('span.green::text').get()}
    
                elif response.xpath(u"//span[contains(text(), '△')]").get():
                    yield{
                        'zaiko': response.css('span.red:nth-of-type(1)::text').get()}
    
                else: yield {
                    'zaiko': response.css('span.upperRight::text').get()}
    
            except:
                pass
    

    将在一列中产生正确的结果

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多