Scrapy csv输出“随机”缺少字段

23c0lvtd  于 2022-12-27  发布在  其他
关注(0)|答案(2)|浏览(132)

我的scrapy crawler正确读取了所有字段,如调试输出所示:

2017-01-29 02:45:15 [scrapy.core.scraper] DEBUG: Scraped from <200 https://www.willhaben.at/iad/immobilien/mietwohnungen/niederoesterreich/krems-an-der-donau/altbauwohnung-wg-geeignet-donaublick-189058451/>
{'Heizung': 'Gasheizung', 'whCode': '189058451', 'Teilmöbliert / Möbliert': True, 'Wohnfläche': '105', 'Objekttyp': 'Zimmer/WG', 'Preis': 1050.0, 'Miete (inkl. MWSt)': 890.0, 'Stockwerk(e)': '2', 'Böden': 'Laminat', 'Bautyp': 'Altbau', 'Zustand': 'Sehr gut/gut', 'Einbauküche': True, 'Zimmer': 3.0, 'Miete (exkl. MWSt)': 810.0, 'Befristung': 'nein', 'Verfügbar': 'ab sofort', 'zipcode': 3500, 'Gesamtbelastung': 1150.0}

但当我使用命令行选项输出csv时

scrapy crawl mietwohnungen -o mietwohnungen.csv --logfile=mietwohnungen.log

缺少某些字段,如输出文件中的相应行所示:

Keller,whCode,Garten,Zimmer,Terrasse,Wohnfläche,Parkplatz,Objekttyp,Befristung,zipcode,Preis
,189058451,,3.0,,105,,Zimmer/WG,nein,3500,1050.0

示例中缺少的字段包括:第一个月
这种情况发生在我抓取的一些值上。需要注意的一点是,不是每个页面都包含相同的字段,因此我根据页面生成字段名。我创建了一个包含所有字段的dict,最后是yield。这就像调试输出所显示的那样工作。但是,一些csv列似乎没有被打印出来。
正如您所看到的,一些列是空白的,因为其他页面显然有这些字段(在示例“Keller”中)。
如果我使用一个较小的列表来抓取,scraper就可以工作(例如,优化我的初始搜索选择,同时在结果中保留一些有问题的页面):

Heizung,Zimmer,Bautyp,Gesamtbelastung,Einbauküche,Miete (exkl. MWSt),Zustand,Miete (inkl. MWSt),zipcode,Teilmöbliert / Möbliert,Objekttyp,Stockwerk(e),Böden,Befristung,Wohnfläche,whCode,Preis,Verfügbar
Gasheizung,3.0,Altbau,1150.0,True,810.0,Sehr gut/gut,890.0,3500,True,Zimmer/WG,2,Laminat,nein,105,189058451,1050.0,ab sofort

我已经更改为python3以避免任何unicode字符串问题。
这是一个bug吗?这似乎也只影响csv输出,如果我输出到xml,所有字段都会打印出来。
我不明白为什么它不能和完整的列表一起工作。唯一的解决办法真的是手工编写csv导出器吗?

hmmo2u0o

hmmo2u0o1#

如果您将抓取结果生成为dict,则CSV列将从第一个生成的dict的键填充:

def _write_headers_and_set_fields_to_export(self, item):
    if self.include_headers_line:
        if not self.fields_to_export:
            if isinstance(item, dict):
                # for dicts try using fields of the first item
                self.fields_to_export = list(item.keys())
            else:
                # use fields declared in Item
                self.fields_to_export = list(item.fields.keys())
        row = list(self._build_row(self.fields_to_export))
        self.csv_writer.writerow(row)

因此,您应该定义并使用显式定义的所有字段填充Item,或者编写自定义的CSVItemExporter

wljmcqd8

wljmcqd82#

基于mizhgun's answer的解决方案:
我创建了一个项目管道来写入csv输出。当迭代通过每个项目时,它存储唯一键集,并在最后写入csv文件。请记住,在调用scrapy crawl时删除-o选项,并将管道添加到settings.py

管道.py

import csv
import logging

class CsvWriterPipeline(object):

    def open_spider(self, spider):
        self.file = open('mietwohnungen.csv', 'w', newline='')
        #if python < 3 use
        #self.file = open('mietwohnungen.csv', 'wb')
        self.items = []
        self.colnames = []

    def close_spider(self, spider):
        csvWriter = csv.DictWriter(self.file, fieldnames = self.colnames)#, delimiter=',')
        logging.info("HEADER: " + str(self.colnames))
        csvWriter.writeheader()
        for item in self.items:
            csvWriter.writerow(item)
        self.file.close()

    def process_item(self, item, spider):
        # add the new fields
        for f in item.keys():
            if f not in self.colnames:
                self.colnames.append(f)

        # add the item itself to the list
        self.items.append(item)
        return item

设置.py

ITEM_PIPELINES = {
    'willhaben.pipelines.CsvWriterPipeline': 300,
}

此答案作为CC BY-SA 3.0下OP MoRe的问题Scrapy csv输出“随机”缺失字段的edit发布。

相关问题