2017-11-23 5 views
1

나는 많은 양의 데이터를 다운로드하기 위해 치료를 사용하고 있습니다. 기본 16 동시 요청을 사용합니다. 가이드에서 알 수 있듯이 공유 변수에서 데이터를 수집하는 파이프 라인 방법 process_item을 사용합니다. 그리고 close_spider에 데이터를 SQL에 저장하십시오. 너무 큰 웹 사이트를로드하면 시스템 메모리가 모두 손실됩니다. 이 문제를 어떻게 피할 수 있습니까?가장 좋은 치료

이제 DB 연결을 하나 사용하여 open_spider 메서드에서 준비했으며 모든 process_item에서 사용할 수 없었습니다.

답변

1

파이프 라인에서 스크랩 된 항목의 목록을 만들고 해당 목록의 크기가 N보다 크면 DB 기능을 호출하여 데이터를 저장하십시오. 내 프로젝트의 100 % 작동 코드입니다. close_spider()을 참조하십시오. 거미 닫을 때 self.items에 N 개 미만의 항목이있을 가능성이 있으므로 self.items 안에있는 나머지 데이터는 거미가 닫히면 DB에 저장됩니다.

from scrapy import signals 

class YourPipeline(object): 

    def __init__(self): 
     self.items = [] 

    def process_item(self, item, spider): 

     self.items.extend([ item ]) 

     if len(self.items) >= 50: 
      self.insert_current_items(spider) 
     return item 

    def insert_current_items(self, spider): 
     for item in self.items: 
      update_query = ', '.join(["`" + key + "` = %s " for key, value in item.iteritems()]) 

      query = "SELECT asin FROM " + spider.tbl_name + " WHERE asin = %s LIMIT 1" 

      spider.cursor.execute(query, (item['asin'])) 

      existing = spider.cursor.fetchone() 

      if spider.cursor.rowcount > 0: 

       query = "UPDATE " + spider.tbl_name + " SET " + update_query + ", date_update = CURRENT_TIMESTAMP WHERE asin = %s" 

       update_query_vals = list(item.values()) 
       update_query_vals.extend([existing['YOUR_UNIQUE_COLUMN']]) 


       try: 
        spider.cursor.execute(query, update_query_vals) 
       except Exception as e: 
        if 'MySQL server has gone away' in str(e): 
         spider.connectDB() 
         spider.cursor.execute(query, update_query_vals) 
        else: 
         raise e 

      else: 

       # This ELSE is likely never to get executed because we are not scraping ASINS from Amazon website, we just import ASINs into DB from another script 
       try: 
        placeholders = ', '.join(['%s'] * len(item)) 
        columns = ', '.join(item.keys()) 
        query = "INSERT INTO %s (%s) VALUES (%s)" % (spider.tbl_name, columns, placeholders) 
        spider.cursor.execute(query, item) 
       except Exception as e: 
        if 'MySQL server has gone away' in str(e): 
         spider.connectDB() 
         spider.cursor.execute(query, item) 
        else: 
         raise e 


     self.items = [] 



    def close_spider(self, spider): 
     self.insert_current_items(spider) 
+0

즉, 다수의 동시 요청도 있습니다. 그들 모두는 self.items 크기를 하나씩 늘린다. 그들의 크기가 50이 될 때 가장 근접한 process_item 새로 고침 목록. 그러나 insert_current_items가 여전히 실행 중이고 다른 50 개 항목이 self.items에서 수집 된 다음 다른 경우. 따라서, 동시에 작동하는 insert_current_items 메소드가있을 것입니다. – user2572790

+1

'self.items'는 전역 변수이므로 몇 번이나 동시에 process_item 메서드를 호출해도 아무 문제가 없습니다 – Umair

+0

예,하지만 spider.cursor.execute (query, update_query_vals) 메서드에서 문제가 발생했습니다. 여러 번 동시에 작동합니까? – user2572790