python爬蟲如何斷點繼續抓取?

最近寫了一個爬蟲,但是圖片非常多,而且鏈接很多,每次要下載要幾個小時,但是我不能把一台電腦沒事開著吧,每次重新打開電腦又要繼續抓取,有沒有辦法像迅雷一樣,採集一半下次打開再繼續採集這樣,不知道我問題描述的具體嗎?有沒有函數或是模塊可以實現這種方法的?


第一條建議是:去租個伺服器啊,現在伺服器又不貴,如果你是學生優惠多多,你要抓那麼多數據的話肯定是要放在伺服器上跑,放電腦上跑多累人啊。

然後再來談一談說如果你真的不願意租伺服器的話。

1、如果說要抓取的url都是有規律的,並且當你因為特殊情況停止之後可以直接從下一個url抓取的。比如:

  • http://xxx.com/pic?page=1
  • http://xxx.com/pic?page=2
  • http://xxx.com/pic?page=3
  • http://xxx.com/pic?page=...

這種情況,你只需要在每次停止的時候存儲一下頁碼等參數即可,最方便的就是在日誌裡面記錄一下。

2、如果可以一次性抓取所有待抓取的url,就把這些url都抓取存儲到資料庫中,也可以放在在redis里,抓完一個扔一個,這樣下次開機的時候就接著下面的url爬取了。

3、如果這都不行,你就每次都重頭來過,不過每次爬取的時候先判斷一下圖片是否已經存在本地了,存在就直接跳過,不存在就下載圖片。

不管什麼方法,目的只有一個:記錄下最後的狀態


方法多種多樣。核心思路是,在本次爬取之後到下一次重新爬取之前,處理好上一次已經爬的狀態。或者說,做好日誌(log)。不僅僅在爬蟲處理斷點時,任何需要跑很久並且都可能需要重啟的程序都同理。我在實際開發中常用的辦法有:

1. 寫一個函數,在每次爬取的開頭更新上一次已經爬的內容。這種方案適合比較規整的爬蟲,或者說樹結構的鏈接節點,比如說一層一層爬某小說網的全部小說。另外一個好處是可以手動處理出現的各種各樣的問題。比如,從別的電腦下載的文件放到自己的文件目錄裡面,可以自動更新上去。

2. 更概括地說,記錄好最後狀態。這是比較通用的方法,比如說每次抓取之後立刻更新資料庫或者更新文件,把已經抓取的鏈接標記,或者乾脆取出來(等價的方法是,先取出來,失敗了再放回去,成功了就不放回去)。然而實時保存意味著程序需要多費一部分功夫做這個事情,因此會產生很多細節問題,比如說連接資料庫的頻率太高等,會在實際問題中影響效率造成問題。

一旦數據量太大,斷點處理就會變成一個大麻煩。比如說我之前在洗160G的文本數據、文件夾層級有好幾層,我沒有使用資料庫(主要是當時快期末考,懶得在實驗室的電腦上折騰資料庫環境),當log文件過大的時候,每次打開log本身就會變成一個極度影響效率的事情。

在實際開發中,這根據數據本身的特點和自己的需求,選擇最適合自己的方案,技巧性比較強,沒有固定的方法。從可維護的角度考慮,優先考慮自己最熟悉的方案,即使可能問題很多,至少自己知道要怎麼改。然後就是已經被別人用過的方案,但是要在類似的環境下模仿到位。如果模仿不到位,經常容易因為一個細節就導致大問題。再然後,如果比較資料庫和文件,總體來說資料庫在邏輯上更清楚,但是資料庫本身的細節問題會是重點;文件更方便更簡單,但是數據量過大,更新本身會成為大問題。

最後,強調一個非常非常重要的問題:做好測試。作為一個無數次坑了自己,然後無數次給程序打補丁的人,我越來越意識到測試的重要性。測試的關鍵在於要設計預期流程和結果,並且全部測試一遍;最好是單獨做一個比較理想的測試集來做這件事情(雖然我經常因為懶不想做……然後反而自己坑自己……)。


可用隊列實現這個。和迅雷的斷點續傳不是一回事。
用一個雙端隊列,存貯採集的url,採集的從隊列pop出,有新的的添加。
不想採集的時候,講還沒有完成的寫到文件中,下次工作時,再讀到隊列中。


爬蟲程序本身應該是無狀態的,任何想要持久化的東西都應該放在資料庫里,mongo、redis、mysql、postgres,或者直接使用文件系統等等。
你需要把任務(url、狀態等)存在資料庫里,這樣即使爬蟲程序暫停了或者崩潰了,下次重啟程序時,資料庫里的東西還在,爬蟲還可以繼續爬取。


這個問題本質上來說,就是處理爬蟲採集過程的異常,完整的解決方案是, 結合 Python 的異常處理機制和日誌處理模塊 logging,對異常記錄,分析和處理。

針對你的特定問題,有個比較簡單的解決方案,就是一個 url 對應一個圖片的文件名稱,你只要加一句 os.path.exists(img_name) 判斷圖片是否已經存在,如果存在就跳過。


所有中斷之後想恢復工作的方法都是一樣的--
保存當前工作的上下文


Scrapy結合MySQL,做了一個小嘗試:Scrapy之斷點續爬


用scrapy呀

在settings.py中加入一行 JOBDIR="pause"

正常運行scrapy crawl xxxx,不想爬時按Ctrl+c結束

下次再運行scrapy crawl xxxx,你就會發現自動從上次停止的地方開始u爬啦


告訴你一些優化小技巧:

多線程爬,爬到圖片鏈接以後丟給wget(它自己會檢查是否下過了文件)。
要點:每個線程開wget以後,一定要卡在讀取wget的輸出流那裡,直到wget完成了一項任務。避免解析太快而開了太多的下載器導致硬體資源或者帶寬不足。

多線程太複雜?單線程直接爬,到圖片鏈接就丟給wget不管,然後主線程休眠一下(自己根據網速和電腦情況來確定休眠時間),不要開太多個wget進程就好了。

斷點續爬:
把爬蟲的入口看作是一棵樹的root,那麼保存相應的任務節點就能斷點續爬了。

改進工作方法:只爬圖片鏈接,全部存資料庫裡面。之後慢慢來下(不過時間久了鏈接可能會失效)

改進方法2:直接wget來down整站(注意下載深度),python寫個工具事後來刪掉那些不要的文件。


兄弟 你爬的是不是1024呀,別問我為什麼知道的。
1.把圖片的url存在資料庫中
2.爬前先判斷文件是否存在,存在就跳過
3.後續只爬取更新的帖子,把資料庫的url建立一個索引,並唯一化,下載新寫入的url即可


可以先把圖片的鏈接先全部抓取下來,存到資料庫中,或者文本。

寫個簡單的下載函數,讀取URL,下載,完成後在標記下已經下載。


這很容易吧,我擦。

將圖片超鏈接去掉Windows非法字元,作為保存的文件名,每次要保存前查看本地是否存在,存在就不抓,這麼簡單的方法。。。

抓圖片這種太簡單了,圖片基本都沒法反爬蟲。。。


使用資料庫或者寫文件,創建一個隊列。

資料庫如果安裝不方便的話可以寫兩個文件,一個記錄抓取完成的,一個記錄任務。

不過每次抓取讀取文件一次比較麻煩而已


採集的圖片總有ID吧,你數據採集連log都沒有記錄嗎,再不濟記住鏈接,鏈接總是有規律的吧。


這個世界上,有種東西,叫做日誌


你需要入門數據儲存和管理。
我記得Python 有可以把dictionary 序列化的函數,你只需要在自己的爬蟲里把進度和待獲取的網頁保存成一個dictionary,然後每完成100條就保存一下dictionary,每次運行程序的時候反序列化就可以了。


睡覺的時候開著電腦抓,我就這樣。。。


學下數據結構,例如隊列,列表,集合,爬過以後鏈接在資料庫或文件中,下次把爬過的放到集合里,重新爬的時候看當前鏈接是否爬過,如果沒有爬過就爬取後加到集合里……大概就這樣


有分析獲取圖片鏈接的程序,把要爬的或等待分析的鏈接放資料庫里,另一個程序按某種次序提取鏈接去爬,修改記錄為正執行,成功爬完的在資料庫做記錄已爬。失敗的放異常表,最後重試異常的。再有個程序掃描資料庫超時記錄,使其重新進入待爬。


生成全部採集url列表,放入redis隊列里,工程小可以寫個txt文本存儲,使用消費者從隊列里pop或者文本里讀取,


推薦閱讀:

python教程看完了,還是不會編程?
Python有哪些常見的、好用的爬蟲框架?
如何去尋找網路爬蟲的需求?
Python實現爬蟲代理池?
python分享中初級爬蟲教程泛濫是否有其語法特徵和生態環境的鍋?

TAG:Python | 數據採集 | 網頁爬蟲 |