我的scrapy搜寻器正确读取所有字段,如调试输出所示:
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
示例中缺少的字段为:Heizung, Teilmöbliert / Möbliert, Miete (inkl. MWSt), Stockwerk(e), Böden, Bautyp, Zustand, Einbauküche, Miete (exkl. MWSt), Verfügbar, Gesamtbelastung
这种情况发生时我抓了一些值。需要注意的一点是,并非每个页面都包含相同的字段,因此我会根据页面生成字段名称。我创建了一个包含所有字段的dict,最后是yield
。这与DEBUG输出显示有效。但是,有些csv列似乎没有打印出来。
正如您所看到的,某些列是空白的,因为其他页面显然具有这些字段(在示例中&#39; Keller&#39;)。
如果我使用较小的列表进行刮取(例如,在保留结果中某些有问题的页面的同时优化我的初始搜索选择),则刮刀有效:
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字符串问题。
这是一个错误吗?这似乎只影响csv输出,如果输出到xml,则打印所有字段。
我不明白为什么它不能与完整列表一起使用。是手动编写csv导出器的唯一解决方案吗?
编辑:解决方案基于@ mizhgun&#39; s answer:
我创建了一个写入csv输出的项目管道。迭代每个项目时,它存储唯一键的集合并最终写入csv文件。请务必在调用-o
并将管道添加到scrapy crawl
时删除settings.py
选项:
pipelines.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
settings.py
ITEM_PIPELINES = {
'willhaben.pipelines.CsvWriterPipeline': 300,
}
答案 0 :(得分:2)
如果您将结果作为dict产生,则将从第一个产生的字典的键中填充CSV列:
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
。