2017-03-05 3 views
0

Wie kann ich Scrapy mitteilen, dass alle erarbeiteten Elemente in zwei Listen aufgeteilt werden sollen? Nehmen wir zum Beispiel an, ich habe zwei Haupttypen von Elementen - article und author. Ich möchte sie in zwei getrennten Listen haben. Gerade jetzt bekomme ich Ausgabe JSON:Scrapy Yield-Elemente als Unterelemente in JSON

[ 
    { 
    "article_title":"foo", 
    "article_published":"1.1.1972", 
    "author": "John Doe" 
    }, 
    { 
    "name": "John Doe", 
    "age": 42, 
    "email": "[email protected]" 
    } 
] 

Wie konvertiere ich es in so etwas?

{ 
    "articles": [ 
    { 
     "article_title": "foo", 
     "article_published": "1.1.1972", 
     "author": "John Doe" 
    } 
    ], 
    "authors": [ 
    { 
     "name": "John Doe", 
     "age": 42, 
     "email": "[email protected]" 
    } 
    ] 
} 

Meine Funktionen für diese Ausgabe von einfach sind, ähnlich wie diese:

def parse_author(self, response): 
     name = response.css('div.author-info a::text').extract_first() 
     print("Parsing author: {}".format(name)) 

     yield { 
      'author_name': name 
     } 

Antwort

2

Artikel mit diesem Setup die Pipeline separat und fügen jeweils entsprechend erreichen:

items.py

class Article(scrapy.Item): 
    title = scrapy.Field() 
    published = scrapy.Field() 
    author = scrapy.Field() 

class Author(scrapy.Item): 
    name = scrapy.Field() 
    age = scrapy.Field() 

spider.py

def parse(self, response): 

    author = items.Author() 
    author['name'] = response.css('div.author-info a::text').extract_first() 
    print("Parsing author: {}".format(author['name'])) 
    yield author 

    article = items.Article() 
    article['title'] = response.css('article css').extract_first() 
    print("Parsing article: {}".format(article['title'])) 

    yield article 

pipelines.py

process_item(self, item, spider): 
    if isinstance(item, items.Author): 
     # Do something to authors 
    elif isinstance(item, items.Article): 
     # Do something to articles 

Ich schlage vor, obwohl dieser Architektur:

[{ 
    "title": "foo", 
    "published": "1.1.1972", 
    "authors": [ 
     { 
     "name": "John Doe", 
     "age": 42, 
     "email": "[email protected]" 
     }, 
     { 
     "name": "Jane Doe", 
     "age": 21, 
     "email": "[email protected]" 
     }, 
    ] 
}] 

Dies macht es alles in einem Punkt gehen.

items.py

class Article(scrapy.Item): 
    title = scrapy.Field() 
    published = scrapy.Field() 
    authors = scrapy.Field() 

spider.py

def parse(self, response): 

    authors = [] 
    author = {} 
    author['name'] = "John Doe" 
    author['age'] = 42 
    author['email'] = "[email protected]" 
    print("Parsing author: {}".format(author['name'])) 
    authors.append(author) 

    article = items.Article() 
    article['title'] = "foo" 
    article['published'] = "1.1.1972" 
    print("Parsing article: {}".format(article['title'])) 
    article['authors'] = authors 
    yield article 
+0

Ich bin mir immer noch nicht sicher, wie man alle Elemente eines bestimmten Typs unter einem JSON Schlüssel zusammenfasst . Wenn die Pipeline so geändert wird, dass '{'author': item} zurückgegeben wird, wird immer noch ein einziger Autorschlüssel für jedes Element erstellt. Ich denke, ich muss alle Elemente in meiner eigenen Liste irgendwo sammeln und dann ganz am Ende als JSON ausgeben, aber ich weiß nicht wohin. ::: Ihre vorgeschlagene Architektur ist gut, wenn ich hauptsächlich Artikel durchblättern möchte. Es macht es beispielsweise sehr viel schwieriger, alle Autoren aufzulisten. –

+0

@MartinMelka Ich habe meine Antwort bearbeitet –

1
raw = [ 
    { 
     "article_title":"foo", 
     "article_published":"1.1.1972", 
     "author": "John Doe" 
    }, 
    { 
     "name": "John Doe", 
     "age": 42, 
     "email": "[email protected]" 
    } 
] 

data = {'articles':[], "authors":[]} 

for a in raw: 

    if 'article_title' in a: 
     data['articles'].extend([ a ]) 

    else: 
     data['articles'].extend([ a ]) 
+0

Ich bin nicht sicher, wie Wörterbücher in Scrapy wie das zu handhaben. 'Ausbeute' aus einer Parsing-Funktion übergibt das Wörterbuch direkt an Scrapy und kann es am Ende nicht verarbeiten. Kannst du bitte auf deine Antwort eingehen? –

+0

@MartinMelka Prozess bedeutet wo? Entschuldigung, dass ich Ihre Frage nicht bekommen habe ... was ich verstehe, ist, dass Ihre Daten in der Pipeline von 'item ['articles'] zugänglich sein sollten.' – Umair