python 高度魯棒性爬蟲的異常和超時問題

爬蟲這類型程序典型特徵是意外多,無法確保每次請求都是穩定的返回統一的結果,要提高魯棒性,能對錯誤數據or超時or程序死鎖等都能進行處理,才能確保程序幾個月不停止。本項目乃長期維護github:反反爬蟲開源庫中積累下來,更多乾貨歡迎star。

目錄:

  • 一:基礎try&except異常處理
  • 二:普通請求函數的超時處理
  • 三:selenium+chrome | phantomjs 的超時處理
  • 四:自定義函數的死鎖or超時處理
  • 五:自定義線程的死鎖or超時處理
  • 六:自重啟的程序設計

一:基礎try&except異常處理

try&except的語句作用不僅僅是要讓其捕獲異常更重要的是讓其忽略異常,因為爬蟲中的絕大多數異常可能重新請求就不存在,因此,發現異常的時候將其任務隊列進行修復其實是個最省力的好辦法。

其次被try包住的語句即使出錯也不會導致整個程序的退出,相信我,你絕對不希望計劃跑一個周末的程序在半夜停止了。

try:n passn #可能出錯的語句nexcept Exception,e:n passn #保留錯誤的url,留待下次重跑n print enfinally:n #無論是否處理了異常都繼續運行n print time.ctime() n

二:請求函數的超時處理

2.1:普通請求:

2.1.1單請求類型:

import requestsnrequests.get(url,timeout=60)n

2.1.2會話保持類型:

import requesocksnsession = requesocks.session()nresponse = session.get(URL,headers=headers,timeout=10)n

三:selenium+chrome | phantomjs 的超時處理

2.2.1:selenium+chrome的超時設置

官網原文:Selenium Python Bindings 2 documentation

顯式等待:、等待某個條件發生,然後再繼續進行代碼。

from selenium import webdrivernfrom selenium.webdriver.common.by import Bynfrom selenium.webdriver.support.ui import WebDriverWaitnfrom selenium.webdriver.support import expected_conditions as ECn ndriver = webdriver.Firefox()ndriver.get("http://somedomain/url_that_delays_loading")ntry:n element = WebDriverWait(driver, 10).until( #這裡修改時間n EC.presence_of_element_located((By.ID, "myDynamicElement"))n )nfinally:n driver.quit()n

隱式等待:是告訴WebDriver在嘗試查找一個或多個元素(如果它們不是立即可用的)時輪詢DOM一定時間。默認設置為0,一旦設置,將為WebDriver對象實例的生命期設置隱式等待。

from selenium import webdriverndriver = webdriver.Firefox()ndriver.implicitly_wait(10) # secondsndriver.get("http://somedomain/url_that_delays_loading")nmyDynamicElement = driver.find_element_by_id("myDynamicElement")n

2.2.2:phantomjs的超時設置

這裡使用不帶selenium的phantomjs,需要使用js。主要設置語句

page.settings.resourceTimeout = 5000; // 等待5秒n

var system = require(system);nvar args = system.args;nvar url = args[1];nvar page = require(webpage).create();npage.settings.resourceTimeout = 5000; // 等待5秒npage.onResourceTimeout = function(e) {ntconsole.log(e.errorCode); //列印錯誤碼ntconsole.log(e.errorString); // 列印錯誤語句ntconsole.log(e.url);t //列印錯誤urlntphantom.exit(1);n};npage.open(url, function(status) {ntif (status === success) {nttvar html = page.evaluate(function() {ntttreturn document.documentElement.outerHTML;ntt});nttconsole.log(html);nt}ntphantom.exit();nt});n//$phantomjs xx.js http://bbs.pcbaby.com.cn/topic-2149414.htmln

四:自定義函數的死鎖or超時處理

這個非常重要!!

python是順序執行的,但是如果下一句話可能導致死鎖(比如一個while(1))那麼如何強制讓他超時呢?他本身如果沒有帶有超時設置的話,就要自己運行信號(import signal)來處理

#coding:utf-8nimport timenimport signaln ndef test(i):n time.sleep(0.999)#模擬超時的情況n print "%d within time"%(i)n return in ndef fuc_time(time_out):n # 此為函數超時控制,替換下面的test函數為可能出現未知錯誤死鎖的函數n def handler(signum, frame):n raise AssertionErrorn try:n signal.signal(signal.SIGALRM, handler)n signal.alarm(time_out)#time_out為超時時間n temp = test(1) #函數設置部分,如果未超時則正常返回數據n return tempn except AssertionError:n print "%d timeout"%(i)# 超時則報錯n nif __name__ == __main__:n for i in range(1,10):n fuc_time(1) n

五:自定義線程的死鎖or超時處理

在某個程序中一方面不適合使用selenium+phantomjs的方式(要實現的功能比較難不適合)因為只能用原生的phantomjs,但是這個問題他本身在極端情況下也有可能停止(在超時設置之前因為某些錯誤)

那麼最佳方案就是用python單獨開一個線程(進程)調用原生phantomjs,然後對這個線程進程進行超時控制。

這裡用ping這個命令先做測試,

import subprocessnfrom threading import Timernimport timen nkill = lambda process: process.kill()n ncmd = ["ping", "http://www.google.com"]nping = subprocess.Popen(n cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)n nmy_timer = Timer(5, kill, [ping])#這裡設定時間,和命令ntry:n my_timer.start()#啟用n stdout, stderr = ping.communicate()#獲得輸出n #print stderrn print time.ctime()nfinally:n print time.ctime()n my_timer.cancel()n

六:自重啟的程序設計

比如程序在某種情況下報錯多次,,那麼滿足條件後,讓其重啟即可解決大多數問題,當然這只不過是治標不治本而已,如果這個程序重啟沒有大問題(例如讀隊列類型)那麼自重啟這是最省力的方式之一。

import time,sys,osndef restart_program():n python = sys.executablen os.execl(python, python, * sys.argv)n nif __name__ == "__main__":n print start...n print u"3秒後,程序將結束...".encode("utf8")n time.sleep(3)n restart_program()n

原創文章,轉載請註明: 轉載自URl-team

本文鏈接地址:python 高度魯棒性爬蟲的異常和超時問題


推薦閱讀:

基於微博數據用 Python 打造一顆「心」
第100篇文章紀念(? ?_?)?
4行Python代碼獲取所在城市天氣預報
【爬蟲】解決封IP問題:1.利用ADSL伺服器
對豆瓣《戰狼2》87767 條短評做詞雲

TAG:Python | 爬虫 | 数据采集 |