2013-08-21 41 views
9

Để tiếp tục xây dựng trên tiêu đề cho câu hỏi này: Tôi đang xóa thông tin khỏi trang web phim. Tôi hiện có một cơ sở dữ liệu MySQL được điền với movie titles, movie urls, v.v. Bây giờ tôi sẽ lấy những dữ liệu đó urls từ cơ sở dữ liệu và đặt chúng làm start_urls của tôi trong một spider mới. Mỗi url là một liên kết đến trang web của [insert abritrary movie], nhiều thông tin hơn được truyền tải. Thông tin mà tôi đang quan tâm là:Phế liệu: Đề xuất cho nhiều lần trả lại/mục vào cơ sở dữ liệu

  • phân phối (tức Fox.)
  • giá
  • giám đốc
  • thể loại (phim hài tức.)
  • diễn viên
  • (tức Thạc-13.)
  • nhà sản xuất/s

Trong số này, nhà phân phối, đánh giá, đạo diễn và thể loại sẽ có một 'điều' liên quan đến họ rom từng trang web phim (một xếp hạng, một đạo diễn, v.v.). Sẽ có nhiều, tất nhiên, nhiều diễn viên và, tùy thuộc, nhiều nhà sản xuất (phim tên lớn hơn/hầu hết các bộ phim). Đây là nơi tôi đang gặp vấn đề. Tôi muốn thiết lập một bảng pipeline' which puts each piece of info in an appropriatewithin my MySQL database. So, a table for director, a table for rating, etc. Each table will also have tiêu đề phim`. Tôi có thể nêu rõ vấn đề như vậy:

Tôi đang gặp sự cố khi điều chỉnh cách xây dựng pipeline thích hợp với spider thích hợp. Tôi không chắc liệu tôi có thể trả lại nhiều thứ từ một con nhện hay không và gửi chúng đến pipelines khác nhau (tạo các mục khác nhau để xử lý các thuộc tính single và một mục khác để xử lý các thuộc tính 'nhiều') hoặc có sử dụng cùng một đường dẫn hay không bằng cách nào đó xác định những gì đi đâu (không chắc chắn nếu tôi chỉ có thể trả lại một điều sau khi cạo). Tôi sẽ hiển thị mã của tôi và hy vọng vấn đề sẽ trở nên rõ ràng hơn. * Lưu ý: nó không phải là chưa complete- Tôi chỉ cố gắng để điền vào chỗ trống với làm thế nào để làm điều này

Spider:

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? 

tôi đã nhận xét trong một số câu hỏi mà có thể không rõ ràng - Tôi không chắc chắn làm thế nào để chỉ đạo tất cả mọi thứ để nó kết thúc trong bảng thích hợp. Điều này có thể rõ ràng hơn khi bạn đọc các đường ống dẫn, đó là:

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 

Tôi nghĩ rằng sẽ làm việc để chỉ đạo việc item để thích hợp table trong cơ sở dữ liệu. Dựa trên điều này, tôi nghĩ rằng nó sẽ làm việc để có một danh sách lớn của items và thêm tất cả mọi thứ với nó, vì vậy:

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) 

Chỉ cần để cho pipeline loại này tất cả ra ngoài với những if báo cáo. Tôi không chắc chắn, tuy nhiên, nếu đây là cách tốt nhất để làm điều này và thực sự sẽ đánh giá cao các đề xuất.

Trả lời

12

Mặt hàng khái niệm, phế liệu thường đề cập đến một "điều" được cạo (trong trường hợp của bạn, một bộ phim) và có các trường đại diện cho dữ liệu tạo thành "điều" này.Vì vậy, xem xét có:

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

Sau đó, khi bạn cạo các mục: phương pháp phân tích cú pháp

item = MovieItem() 

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

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

return item 

Spider nên luôn luôn trả lại hoặc mang lại một trong hai đối tượng scrapy.item.Item hoặc đối tượng scrapy.http.Request.

Từ đó, cách bạn xử lý MovieItems tùy thuộc vào bạn. Bạn có thể có một đường ống dẫn cho mỗi thuộc tính của MovieItem, nhưng nó không được khuyến nghị. Những gì tôi muốn giới thiệu thay vì là có một đối tượng MySQLPersistancePipeline duy nhất có các phương thức để duy trì từng trường của MovieItem. Vì vậy, một cái gì đó như:

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

Cảm ơn bạn đã dành thời gian trả lời! Tôi sẽ cung cấp cho nó một kiểm tra và xem nó như thế nào fares- sẽ đánh dấu giải quyết nếu nó là tốt! Cảm ơn một lần nữa! – DMML

+0

Câu trả lời tuyệt vời, @audiodude! Tại sao nhiều đường ống không được khuyến cáo? –

Các vấn đề liên quan