2015-10-23 23 views
1

所以我的蜘蛛需要一個網站列表,它通過start_requests爬過每個網站,其中yieldrequest通過item作爲meta如果我不知道什麼時候蜘蛛會完成,何時返回一個物品?

然後,蜘蛛探索單個網站的所有內部鏈接,並收集到item的所有外部鏈接。問題是,我不知道什麼時候蜘蛛完成爬取所有的內部鏈接,所以我不能yielditem

class WebsiteSpider(scrapy.Spider): 
    name = "web" 

    def start_requests(self): 
     filename = "websites.csv" 
     requests = [] 
     try: 
      with open(filename, 'r') as csv_file: 
       reader = csv.reader(csv_file) 
       header = next(reader) 
       for row in reader: 
        seed_url = row[1].strip() 
        item = Links(base_url=seed_url, on_list=[]) 
        request = Request(seed_url, callback=self.parse_seed) 
        request.meta['item'] = item 
        requests.append(request) 
      return requests 
     except IOError: 
      raise scrapy.exceptions.CloseSpider("A list of websites are needed") 

    def parse_seed(self, response): 
     item = response.meta['item'] 
     netloc = urlparse(item['base_url']).netloc 
     external_le = LinkExtractor(deny_domains=netloc) 
     external_links = external_le.extract_links(response) 
     for external_link in external_links: 
      item['on_list'].append(external_link) 

     internal_le = LinkExtractor(allow_domains=netloc) 
     internal_links = internal_le.extract_links(response) 

     for internal_link in internal_links: 
      request = Request(internal_link, callback=self.parse_seed) 
      request.meta['item'] = item 
      yield request 
+0

你能展示你當前的蜘蛛代碼嗎?謝謝。 – alecxe

+0

@alecxe編輯! –

回答

0

start_requests方法需要得到Request對象。您不需要返回請求列表,但僅在準備就緒時產生請求,這是可行的,因爲scrapy請求是異步的。

同樣的情況發生在物品上,只要你認爲物品已經準備就緒,你只需要放棄你的物品,我會建議你的情況來檢查是否沒有更多的internal_links來放棄物品,或者你也可以許多項目,只要你想,然後再檢查哪一個是最後(或者一個具有更多數據):

class WebsiteSpider(scrapy.Spider): 
    name = "web" 

    def start_requests(self): 
     filename = "websites.csv" 
     requests = [] 
     try: 
      with open(filename, 'r') as csv_file: 
       reader = csv.reader(csv_file) 
       header = next(reader) 
       for row in reader: 
        seed_url = row[1].strip() 
        item = Links(base_url=seed_url, on_list=[]) 
        yield Request(seed_url, callback=self.parse_seed, meta = {'item'=item}) 
     except IOError: 
      raise scrapy.exceptions.CloseSpider("A list of websites are needed") 

    def parse_seed(self, response): 
     item = response.meta['item'] 
     netloc = urlparse(item['base_url']).netloc 
     external_le = LinkExtractor(deny_domains=netloc) 
     external_links = external_le.extract_links(response) 
     for external_link in external_links: 
      item['on_list'].append(external_link) 

     internal_le = LinkExtractor(allow_domains=netloc) 
     internal_links = internal_le.extract_links(response) 
     if internal_links: 
      for internal_link in internal_links: 
       request = Request(internal_link, callback=self.parse_seed) 
       request.meta['item'] = item 
       yield request 
     else: 
      yield item 

你可以做的另一件事情是創建一個extension做你需要的spider_closed方法什麼和做什麼無論你想知道什麼時候蜘蛛結束。

+0

感謝您的回覆。當內部鏈接用完時,我想到了讓步,但正如您所提到的,由於scrapy異步運行,即使某個網頁沒有任何內部鏈接,其他一些網頁可能正在等待處理。我已經使用項目加載器重建了scrapy,並且我想我可能會創建一個新的函數,該函數接收字典並在調用「closed」時將其輸出到JSON。 –

+0

完美,所以你要創建自己的擴展權嗎?我認爲這是最好的,也是在任何時候都會產生物品,可以幫助你記錄蜘蛛的工作方式,之前我做過類似的事情。 – eLRuLL

+0

你可能不得不在這個問題上教育我,但我並不真正瞭解使用擴展的好處。從我讀的內容來看,這聽起來像是實現了一個Python類還是一個函數?我想要做的是在蜘蛛完成對所有種子網站的爬行時返回JSON,並且我認爲['closed'](http://doc.scrapy.org/en/latest/topics/spiders.html? highlight = closed#scrapy.spiders.Spider.closed)方法處理這個問題,所以我需要實現JSON導出器,一旦調用'closed'就會被調用。 –

相關問題