2017-01-29 5 views
1

マイscrapyクローラは、正しくデバッグ出力が示すように、すべてのフィールドを読み取りますScrapyのCSV出力「ランダム」不足している分野

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

これは、私が擦ったいくつかの値で起こります。注目すべきは、すべてのページに同じフィールドが含まれているわけではないため、ページに応じてフィールド名が生成されるということです。私は存在するすべてのフィールドと最後にyieldを含む辞書を作成します。これは、DEBUGの出力が示すように機能します。ただし、一部のcsv列は印刷されていないようです。

他のページに明らかにこれらのフィールドがあるため(「Keller」の例のように)、一部の列は空白になっています。

私は(結果では問題のページの一部を維持しながら、例えば私のイニシャルサーチ選択を絞り込む)こすりする小さなリストを使用する場合スクレーパー作品:

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に変更されましたユニコード文字列の問題。

これはバグですか?これはまた、すべてのフィールドがxmlに出力された場合にのみcsv出力に影響するようです。

なぜ完全なリストでは機能しないのかわかりません。本当にCSVエクスポータを手動で作成する唯一のソリューションはありますか?


編集:SOLUTION @ mizhgunのanswerに基づく:

私はCSV出力を書き込み、アイテムのパイプラインを作成しました。すべてのアイテムを反復処理すると、一意のキーのセットが格納され、最後にcsvファイルが書き込まれます。あなたは辞書のようにスクレイプ結果を得た場合

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

たとえば、私はデバッグ出力で 'Keller'カラムを見ることができず、逆に'Teilmöbliert/Möbliert'をCSVカラムとして見ることができません。あなたが列とフィールドを混乱させたように見えますが、あなたのプロジェクトで 'FEED_EXPORT_FIELDS'設定を使用していますか? – mizhgun

+0

はい、私は言葉の列とフィールドを同じ意味で使用していますので、同じ意味です。ただし、一部のフィールドは列として出力されません。私が説明したように、csvに 'Keller'カラムがありますが、この特定のエントリのデバッグ出力にはない理由は、他のエントリにはKellerフィールドがありますが、この特定のものはありません。 (私はこの記事の多くのcsv行のうちの1つだけを表示しています) – MoRe

+0

また、フィールドの名前がわからないので、私は 'FEED_EXPORT_FIELDS'を使っていません。ページ)と私は彼らが印刷されている順序には気にしません。 csvの出力に 'Teilmöbliert/Möbliert'という名前の列がないのはまさに私の質問です;-)明らかに小さな同じコードを使用してリスト... – MoRe

答えて

2

scrapy crawlを呼び出し、settings.pyにパイプラインを追加-oオプションを削除覚えておいてください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と入力してください。

+0

ああ、それは意味がある、ありがとう! – MoRe

関連する問題