2013-08-21 8 views
9

इस प्रश्न के लिए शीर्षक पर आगे विस्तार करने के लिए: मैं फिल्म वेबसाइट से जानकारी को स्क्रैप कर रहा हूं। मेरे पास वर्तमान में MySQL डेटाबेस movie titles, movie urls आदि के साथ आबादी वाला है। अब मैं डेटाबेस से उन urls को ले जा रहा हूं और उन्हें start_urls के रूप में एक नए spider के भीतर सेट कर रहा हूं। प्रत्येक url [अनुचित फिल्म डालने] के वेबपृष्ठ का एक लिंक है, और अधिक जानकारी व्यक्त की जाती है। जानकारी मैं में दिलचस्पी रखता हूँ है:स्केपर: एकाधिक रिटर्न/डेटाबेस के लिए सुझाव

  • वितरक (यानी फॉक्स।)
  • रेटिंग
  • निदेशक
  • शैली (यानी कॉमेडी।)
  • अभिनेताओं
  • (यानी पीजी -13।)
  • निर्माता/एस
इनमें से

, वितरक, रेटिंग, निर्देशक और शैली होगा एक 'बात' च उनसे जुड़े रोम प्रत्येक मूवी वेबपेज (एक रेटिंग, एक निदेशक, आदि)। बेशक, कई अभिनेता और, कई उत्पादक (बड़े नाम की फिल्में/अधिकांश फिल्में) के आधार पर कई होंगे। यह वह जगह है जहां मुझे कोई समस्या है। मैं 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 मूवी शीर्षक 'स्थापित करना चाहता हूं। मैं समस्या को स्वयं ही बता सकता हूं:

मुझे उचित spider के साथ उपयुक्त 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 

मुझे लगता है कि उचित table डेटाबेस के भीतर करने के लिए item निर्देशित करने के लिए काम करेंगे: यह और अधिक स्पष्ट है जब आप पाइपलाइन है, जो पढ़ा जा सकता है। इस आधार पर, मुझे लगता है कि यह 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 वस्तुओं उपज चाहिए।

वहां से, आप मूवीइटम को कैसे संसाधित करते हैं आप पर निर्भर करता है। मूवीआईटम की प्रत्येक संपत्ति के लिए आपके पास पाइपलाइन हो सकती है, लेकिन इसकी अनुशंसा नहीं की जाती है। इसके बजाय मैं एकमात्र 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

ग्रीट उत्तर, @audiodude! क्यों कई पाइपलाइनों की सिफारिश नहीं की जाती है? –

संबंधित मुद्दे