2013-08-21 12 views
9

この質問の見出しをさらに詳しく説明すると、私は映画のウェブサイトから情報を盗んでいます。私は現在、movie titles,などのデータが入っているMySQLデータベースを持っています。今度はurlsをデータベースから取り出して、を新しいspiderに設定します。各urlは、[abritrary movie]のウェブページを挿入するためのリンクです。さらに多くの情報が伝えられます。私が興味の情報は次のとおりです。Scrapy:複数の返品/アイテムのデータベースへの提出

  • 販売代理店(すなわちフォックス。)
  • 評価(すなわちPG-13。)
  • ディレクター
  • ジャンル(すなわちコメディ。)
  • 俳優
  • これらのうち
  • プロデューサー/ sの

、販売代理店、評価、監督、ジャンルは彼らFに関連する一つ「もの」を持っています各ムービーのウェブページ(1つの評価、1つのディレクターなど)。もちろん、複数の俳優、複数のプロデューサー(大名映画/大部分の映画)が複数存在します。これは私が問題を抱えているところです。私はpipeline' which puts each piece of info in an appropriateテーブルwithin my MySQL database. So, a table for director, a table for rating, etc. Each table will also haveムービータイトル `を確立したいと思います。私はそのように問題自体を次のように述べることができます:

適切なpipelineを適切に構成する方法を調整することに問題があります。spiderです。私は1つのスパイダーから複数のものを返すことができるかどうかは分かりません。pipelinessingleの属性を扱うために異なるアイテムを作成し、 'multiple'属性を扱うために別のアイテムを作成します)、または同じパイプラインを使用するかどうか、何とかどこに行くのかを指定します(私が掻き取った後に1つしか返せないかどうかはわかりません)。私は自分のコードを表示し、うまくいけば問題はより明確になるでしょう。 *注:私は不明かもしれ質問の数にコメントしました

class ActorSpider(BaseSpider): 
    import sys; sys.path.append("/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages") 
    import MySQLdb 
    db = MySQLdb.connect(db = 'testdb', user='testuser', passwd='test') 
    dbc = db.cursor() 
    name = 'ActorSpider' 
    allowed_domains = ['movie website'] 
    #start_urls = #HAVE NOT FILLED THIS IN YET- WILL BE A SELECT STATEMENT, GATHERING ALL URLS 

    def parse(self, response): 

     hxs = HtmlXPathSelector(response) 

     #Expect only singular items (ie. one title, one rating, etc.) 

     single_info = SingleItem() 
     title = hxs.select('[title tags here]').extract() 
     distributor = hxs.select('[distributor tags here]').extract() 
     rating = hxs.select('[rating tags here]').extract() 
     director = hxs.select('[director tags here]').extract() 
     genre = hxs.select('[genre tags here]').extract() 

     single_items = [] 
     single_info['title'] = title 
     single_info['distributor'] = distributor 
     single_info['rating'] = rating 
     single_info['director'] = director 
     single_info['genre'] = genre   
     single_items.append(single_info) #Note: not sure if I want to return this or the single info 

     #return single_items 


     #Multiple items in a field 

     multi_info = MultiItem() 
     actors = hxs.select('[actor tags here]').extract() 
     producers = hxs.select('[producer tags here]').extract() 

     actor_items= [] 
     for i in range(len(actors)): 
      multi_info['title'] = title 
      multi_info['actor'] = actors[i] 
      actor_items.append(multi_info) 

    #return actor_items - can I have multiple returns in my code to specify which pipeline is used, or which table this should be inserted into 

     producer_items = [] 
     for i in range(len(producers)): 
      multi_info['title'] = title 
      multi_info['producer'] = producers[i] 
      producer_items.append(multi_info) 
     #return producer_items - same issue - are multiple returns allowed? Should I try to put both the 'single items' and 'multiple items' in on big 'items' list? Can scrapy figure that out or how would I go about specifying? 

:私がちょうどこの

スパイダーを行う方法で空白を埋めるためにしようとしているまだcomplete-ではありません - 私はそれが適切なテーブルに終わるようにすべてを指示する方法がわかりません。

class IndMoviePipeline(object): 

    def __init__(self): 
     'initiate the database connnection' 
     self.conn = MySQLdb.connect(user='testuser', passwd='test', db='testdb', host='localhost', charset='utf8', use_unicode=True) 
     self.cursor = self.conn.cursor() 

    def process_item(self, item, spider): 

     try: 
      if 'producer' in item: 
        self.cursor.execute("""INSERT INTO Producers (title, producer) VALUES (%s, %s)""", (item['title'], item['producer'])) 
      elif 'actor' in item: 
        self.cursor.execute("""INSERT INTO Actors (title, actor) VALUES (%s, %s)""", (item['title'], item['actor'])) 
      else: 
        self.cursor.execute("""INSERT INTO Other_Info (title, distributor, rating, director, genre) VALUES (%s, %s, %s, %s, %s)""", (item['title'], item['distributor'], item['rating'], item['director'], item['genre'])) #NOTE: I will likely change 'Other_Info' table to just populating the original table from which the URLS will be pulled 
      self.conn.commit() 
     except MySQLdb.Error, e: 
      print "Error %d: %s" % (e.args[0], e.args[1]) 

     return item 

私はそれがデータベース内の適切なtableitemを指示するために働くだろうと思う:あなたがあるパイプラインを、読むとき、これは、より明確にすることがあります。これに基づき、私はそれはそう、itemsの一つの大きなリストを持っており、それにすべてを追加するために働くだろうと思う:

items = [] 
items.append(single_info) 

for i in range(len(producers)): 
     multi_info['title'] = title 
     multi_info['producer'] = producers[i] 
     items.append(multi_info) 

for i in range(len(actors)): 
     multi_info['title'] = title 
     multi_info['actor'] = actors[i] 
     items.append(multi_info) 

はちょうどこのすべてのアウトそれらif文とpipeline並べ替えをさせます。しかし、これを実行する最善の方法であり、提案を本当に感謝しているのであれば、私は確信していません。

答えて

12

概念的に言えば、アイテムは一般的に、あなたのケースでは映画を傷つけている単一の「もの」を指し、この「もの」を構成するデータを表すフィールドを持っています。そうすることを検討:

class MovieItem(scrapy.item.Item): 
    title = Field() 
    director = Field() 
    actors = Field() 

あなたがアイテムをこすりときに:

item = MovieItem() 

title = hxs.select('//some/long/xpath').extract() 
item['title'] = title 

actors = hxs.select('//some/long/xpath').extract() 
item['actors'] = actors 

return item 

スパイダーの解析方法は、常にscrapy.item.Itemオブジェクトまたはscrapy.http.Requestオブジェクトのいずれかを返すか、得られるはず。

ここから、MovieItemをどのように処理するかはあなた次第です。 MovieItemのプロパティごとにパイプラインを作成することもできますが、お勧めしません。その代わりに、MovieItemの各フィールドを永続化するメソッドを持つ1つのMySQLPersistancePipelineオブジェクトを用意することをお勧めします。そうですね、

class MySQLPersistancePipeline(object): 
    ... 
    def persist_producer(self, item): 
    self.cursor.execute('insert into producers ...', item['producer']) 

    def persist_actors(self, item): 
    for actor in item['actors']: 
     self.cursor.execute('insert into actors ...', actor) 

    def process_item(self, item, spider): 
    persist_producer(item) 
    persist_actors(item) 
    return item 
+0

お返事ありがとうございました!私はそれに小切手をつけ、どのように運賃が良いのか分かります。再度、感謝します! – DMML

+0

Greate answer、@ududude!なぜ複数のパイプラインが推奨されないのですか? –