2017-04-12 65 views
1

我正在使用scrapy通過身份驗證來抓取網站。
我希望能夠挽救爬行的狀態,我用Scrapy在恢復之前做一些事情

scrapy crawl myspider -s JOBDIR=mydir 

後,我用同樣的命令恢復我希望能夠它之前登錄到網站重新安排所有已保存要求。

基本上,我想確保我的功能login()after_login()將在任何其他請求被調度和執行之前被調用。而且我不想使用Cookie,因爲它們不允許我暫停漫長的爬行。
我可以在start_requests()中調用login(),但是這隻有在我第一次運行爬蟲時纔有效。

class MyCrawlSpider(CrawlSpider): 
    # ... 

    START_URLS = ['someurl.com', 'someurl2.com'] 
    LOGIN_PAGE = u'https://login_page.php' 

    def login(self): 
     return Request(url=self.LOGIN_PAGE, callback=self.login_email, 
         dont_filter=True, priority=9999)  

    def login_form(self, response): 
     return FormRequest.from_response(response, 
              formdata={'Email': 'myemail', 
                'Passwd': 'mypasswd'}, 
              callback=self.after_login, 
              dont_filter=True, 
              priority=9999) 

    def after_login(self, response): 
     if "authentication failed" in response.body: 
      self.logger.error("Login failed") 
      return 
     else: 
      print("Login Successful!!") 
      self.is_logged_in = True 
      for url in self.START_URLS: 
       yield Request(url, callback=self.parse_artists_json, dont_filter=True) 

底線:有,當我恢復與-s JOBDIR=...選項補賽之前的請求之前爬行,這將始終調用任何回調?我會用它來撥打login()方法。

回答

2

可以使用spider_opened信號(more here

此功能旨在爲蜘蛛和其他初始化資源分配,因此它不指望你從那裏得到Request對象。

你可以通過有一個掛起的請求數組來解決這個問題。這是必需的,因爲scrapy不允許您手動調度請求。

然後,恢復蜘蛛後,你可以排隊登錄的隊列中的第一個請求:

def spider_opened(self, spider): 
    self.spider.requests.insert(0, self.spider.login()) 

您還需要添加一個next_request方法到您的蜘蛛

def next_request(self): 
    if self.requests: 
     yield self.requests.pop(0) 

和隊列你所要求的全部添加到requests陣列中,並且調用next_request添加每個方法的結尾:

def after_login(self, response): 
    if "authentication failed" in response.body: 
     self.logger.error("Login failed") 
     return 
    else: 
     print("Login Successful!!") 
     self.is_logged_in = True 
     if not self.requests: 
      for url in self.START_URLS: 
       self.requests.append(Request(url, callback=self.parse_artists_json, dont_filter=True) 

    yield self.next_request() 
+0

謝謝,@VMRuiz,我有一些類似的解決方案。我檢查了我還沒有登錄,登錄未安排,然後我在我的解析方法中安排了登錄請求。你的解決方案比較乾淨,但是它不能解決以下**問題**:在第一次調用解析方法時,調度程序已經有一個從文件中恢復的請求隊列。由於scrapy異步工作,它會在發送登錄前發送多個請求。 – Temak

+0

使用此係統,只能同時安排一個請求。最糟糕的情況是,調度程序將在嘗試再次登錄之前處理第一個未決請求。在這種情況下,您可以檢查請求是否因登錄失敗而重新排隊。 – VMRuiz

相關問題