2017-07-18 14 views
0

私はPythonで自分の知識をリフレッシュしながらScrapyを使う方法を学んでいますか?Scrapy - 入れ子になったJSONオブジェクトの作成

現在、私はimdb top 250のリストで遊んでいますが、JSON出力ファイルで苦労しています。

私の現在のコードは次のとおりです。

# -*- coding: utf-8 -*- 
import scrapy 

from top250imdb.items import Top250ImdbItem 


class ActorsSpider(scrapy.Spider): 
    name = "actors" 
    allowed_domains = ["imdb.com"] 
    start_urls = ['http://www.imdb.com/chart/top'] 

    # Parsing each movie and preparing the url for the actors list 
    def parse(self, response): 
     for film in response.css('.titleColumn'): 
      url = film.css('a::attr(href)').extract_first() 
      actors_url = 'http://imdb.com' + url[:17] + 'fullcredits?ref_=tt_cl_sm#cast' 
      yield scrapy.Request(actors_url, self.parse_actor) 

    # Finding all actors and storing them on item 
    # Refer to items.py 
    def parse_actor(self, response): 
     final_list = [] 
     item = Top250ImdbItem() 
     item['poster'] = response.css('#main img::attr(src)').extract_first() 
     item['title'] = response.css('h3[itemprop~=name] a::text').extract() 
     item['photo'] = response.css('#fullcredits_content .loadlate::attr(loadlate)').extract() 
     item['actors'] = response.css('td[itemprop~=actor] span::text').extract() 

     final_list.append(item) 

     updated_list = [] 

     for item in final_list: 
      for i in range(len(item['title'])): 
       sub_item = {} 
       sub_item['movie'] = {} 
       sub_item['movie']['poster'] = [item['poster']] 
       sub_item['movie']['title'] = [item['title'][i]] 
       sub_item['movie']['photo'] = [item['photo']] 
       sub_item['movie']['actors'] = [item['actors']] 
       updated_list.append(sub_item) 
      return updated_list 

と私の出力ファイルは私にこのJSON組成を与えている:

[ 
    { 
    "movie": { 
     "poster": ["https://images-na.ssl-images-amazon.com/poster..."], 
     "title": ["The Shawshank Redemption"], 
     "photo": [["https://images-na.ssl-images-amazon.com/photo..."]], 
     "actors": [["Tim Robbins","Morgan Freeman",...]]} 
    },{ 
    "movie": { 
     "poster": ["https://images-na.ssl-images-amazon.com/poster..."], 
     "title": ["The Godfather"], 
     "photo": [["https://images-na.ssl-images-amazon.com/photo..."]], 
     "actors": [["Alexandre Rodrigues", "Leandro Firmino", "Phellipe Haagensen",...]]} 
    } 
] 

が、私はこれを達成するために探しています:

{ 
    "movies": [{ 
    "poster": "https://images-na.ssl-images-amazon.com/poster...", 
    "title": "The Shawshank Redemption", 
    "actors": [ 
     {"photo": "https://images-na.ssl-images-amazon.com/photo...", 
     "name": "Tim Robbins"}, 
     {"photo": "https://images-na.ssl-images-amazon.com/photo...", 
     "name": "Morgan Freeman"},... 
    ] 
    },{ 
    "poster": "https://images-na.ssl-images-amazon.com/poster...", 
    "title": "The Godfather", 
    "actors": [ 
     {"photo": "https://images-na.ssl-images-amazon.com/photo...", 
     "name": "Marlon Brando"}, 
     {"photo": "https://images-na.ssl-images-amazon.com/photo...", 
     "name": "Al Pacino"},... 
    ] 
    }] 
} 

を私のitems.pyファイルには次のものがあります:

import scrapy 


class Top250ImdbItem(scrapy.Item): 
    # define the fields for your item here like: 
    # name = scrapy.Field() 

    # Items from actors.py 
    poster = scrapy.Field() 
    title = scrapy.Field() 
    photo = scrapy.Field() 
    actors = scrapy.Field() 
    movie = scrapy.Field() 
    pass 

私は次のことを承知している:私の結果が順番に出てきていない

  1. 、Webページのリストの第一の映画はいつも私の出力ファイルの最初の映画ですが、残りはありますない。私はまだそれに取り組んでいます。

  2. 私は同じことをすることができますが、Top250ImdbItem()で作業していますが、それはより詳細な方法で行われます。

  3. 私のJSONには完璧なレイアウトではないかもしれませんが、完全な方法や「唯一の方法」がないことはわかっていますが、提案が歓迎されています。

  4. 一部の俳優は写真がなく、実際には別のCSSセレクタを読み込みます。現時点では、「画像サムネイルなし」にならないようにしたいので、これらの項目を空のままにしても構いません。

例:

{"photo": "", "name": "Al Pacino"} 
+0

'' dict'を使用すると '映画で始まる(scrapy.Item)'を使用しないでください:[] '。 – stovfl

+0

ねえ、@ stovflあなたはもう少し詳しく説明できますか? – ricardoNava

答えて

0

Question: ... struggling with a JSON output file


Note: Can't use your ActorsSpider , get Error: Pseudo-elements are not supported.

# Define a `dict` **once** 
top250ImdbItem = {'movies': []} 

def parse_actor(self, response): 
    poster = response.css(... 
    title = response.css(... 
    photos = response.css(... 
    actors = response.css(... 

    # Assuming List of Actors are in sync with List of Photos 
    actors_list = [] 
    for i, actor in enumerate(actors): 
     actors_list.append({"name": actor, "photo": photos[i]}) 

    one_movie = {"poster": poster, 
       "title": title, 
       "actors": actors_list 
       } 

    # Append One Movie to Top250 'movies' List 
    top250ImdbItem['movies'].append(one_movie) 
+0

オクラホルそれはあなたがそれを実行することはできませんが、実際にはまったく同じコードを使用している、私もその問題をチェックし、あなたがそれを実行することができるかどうかを確認するために更新しますそれらの提案を試してみてください。実際に写真と俳優はまだ同期していません。それでもやり方は分かりますが、あなたの助けは実際には素晴らしいものです。 – ricardoNava

+0

修正した作業コードをここにコメントとして投稿して、現在のものを編集するか、そのままそのまま残しておきますか? – ricardoNava

+0

あなたの質問を[編集]し、変更されたパートのみを追加してください – stovfl

関連する問題