有時候我們爬取數據跑了半天,突然報錯了,例如網絡中斷,我們想繼續爬取,不需程序從頭開始爬取,可以采取下面的方案
要想程序繼續從斷開的位置爬取,最好的方案就是將每次爬取的url存儲到數據庫中,程序每爬取一個url判斷數據庫中是否存在存在說明爬取過了,跳過本次url,如果沒有,那就證明沒有爬取過,程序繼續爬取..額等等,好像有瑕疵
假設有這么一種情況,程序爬取一個url爬了一半,就會有2種情況,要么數據庫內沒有url,程序繼續爬取,會有重復數據,要么數據庫中存在url,那么程序跳過,獲取數據不完整,當前url有些數據沒有獲取到,采用第一種情況吧,存儲數據采用set集合方式
參考方法:https://zhuanlan.zhihu.com/p/26810901
在scrapy中我想不用多說了,用過scrapy框架的應該都知道,本身scrapy就已經內置了一個參數jobs持久化設置
要啟用持久化支持,你只需要通過 JOBDIR
設置 job directory 選項。這個路徑將會存儲 所有的請求數據來保持一個單獨任務的狀態(例如:一次spider爬取(a spider run))。必須要注意的是,這個目錄不允許被不同的spider 共享,甚至是同一個spider的不同jobs/runs也不行。也就是說,這個目錄就是存儲一個 單獨 job的狀態信息。
怎么使用
要啟用一個爬蟲的持久化,運行以下命令:
scrapy crawl somespider -s JOBDIR=crawls/somespider-1
然后,你就能在任何時候安全地停止爬蟲(按Ctrl-C或者發送一個信號)。恢復這個爬蟲也是同樣的命令:
scrapy crawl somespider -s JOBDIR=crawls/somespider-1
保持狀態
有的時候,你希望持續保持一些運行長時間的蜘蛛的狀態。這時您可以使用 spider.state
屬性, 該屬性的類型必須是dict. scrapy提供了內置擴展負責在spider啟動或結束時,從工作路徑(job directory)中序列化、存儲、加載屬性。
下面這個例子展示了使用spider state的回調函數(callback)(簡潔起見,省略了其他的代碼):
def parse_item(self, response): # parse item here self.state['items_count'] = self.state.get('items_count', 0) + 1
持久化的一些坑
如果你想要使用Scrapy的持久化支持,還有一些東西您需要了解:
請求序列化
請求是由 pickle 進行序列化的,所以你需要確保你的請求是可被pickle序列化的。 這里最常見的問題是在在request回調函數中使用 lambda
方法,導致無法序列化。
例如, 這樣就會有問題:
def some_callback(self, response): somearg = 'test' return scrapy.Request('http://www.example.com', callback=lambda r: self.other_callback(r, somearg)) def other_callback(self, response, somearg): print "the argument passed is:", somearg
這樣才對:
def some_callback(self, response): somearg = 'test' return scrapy.Request('http://www.example.com', meta={'somearg': somearg}) #這里的實例代碼有錯,應該是(譯者注) # return scrapy.Request('http://www.example.com', meta={'somearg': somearg}, callback=self.other_callback) def other_callback(self, response): somearg = response.meta['somearg'] print "the argument passed is:", somearg