2013-08-21 7 views
9

이 질문의 제목을 자세히 설명하려면 다음을 수행하십시오. 영화 웹 사이트의 정보를 긁어 모으고 있습니다. 나는 현재 movie titles, movie urls 등으로 채워진 MySQL 데이터베이스를 보유하고 있습니다. 이제 urls을 데이터베이스에서 가져오고 새 을 새 spider으로 설정하려고합니다. 각 url은 [abritrary movie]의 웹 페이지에 대한 링크이며 훨씬 더 많은 정보가 전달됩니다. 내가 관심이있는 정보는 다음과 같습니다Scrapy : 여러 반품/데이터베이스에 대한 제안

  • 유통 (즉, 폭스.)
  • 평가
  • 이사
  • 장르 (예 : 코미디.)
  • 배우
  • (즉 13 세.) f를 그들과 관련된
  • 생산자/S 이들의

, 유통, 평가, 감독과 장르가 가진 것 하나 '일' 롬 각 영화 웹 페이지 (한 등급, 한 감독 등). 물론 다수의 배우와 여러 제작자 (더 큰 이름의 영화/대부분의 영화)가있을 것입니다. 이것은 내가 문제가있는 곳입니다. 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을 구성하는 방법을 조정하는 데 문제가 있습니다. 하나의 거미에서 여러 가지를 반환 할 수 있는지 여부를 다른 pipelines (single 속성을 처리 할 다른 항목을 만들고 '다중'속성을 처리 할 다른 항목을 만들 수 있는지) 또는 동일한 파이프 라인을 사용할 것인지 어떻게 든 어디서 가는지 지정하십시오 (내가 긁어 모으고 나면 한 가지만 돌려 줄 수 있는지 확실하지 않습니다). 내 코드를 보여 주며 문제가 더 명확 해지기를 바랍니다. * 참고 : 불분명 한을 할 수있다 나는 많은 질문에 댓글을 달았습니다

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) 

는 그냥 pipeline 종류의 사람들 if 문이 모두 아웃시키는. 나는 이것이 최선의 방법이고 제안을 정말로 고맙게 여긴다면 확실하지 않다.

답변

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의 각 필드를 유지하는 메소드가있는 단일 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, @audiodude! 왜 여러 파이프 라인이 권장되지 않는가? –