前一節咱們瞭解了請求的發送過程,可是在網絡很差的狀況下,若是出現了異常,該怎麼辦呢?這時若是不處理這些異常,程序極可能因報錯而終止運行,因此異常處理仍是十分有必要的。html
urllib的error
模塊定義了由request
模塊產生的異常。若是出現了問題,request
模塊便會拋出error
模塊中定義的異常。nginx
URLError類來自urllib庫的error模塊,它繼承自OSError類,是error異常模塊的基類,由request模塊生的異常均可以經過捕獲這個類來處理。json
它具備一個屬性reason,即返回錯誤的緣由。ubuntu
下面用一個實例來看一下:api
from urllib import request, error
try:
response = request.urlopen('http://cuiqingcai.com/index.htm')
except error.URLError as e:
print(e.reason)
複製代碼
咱們打開一個不存在的頁面,照理來講應該會報錯,可是這時咱們捕獲了URLError這個異常,運行結果以下:bash
Not Found
複製代碼
程序沒有直接報錯,而是輸出瞭如上內容,這樣經過如上操做,咱們就能夠避免程序異常終止,同時異常獲得了有效處理。服務器
它是URLError
的子類,專門用來處理HTTP請求錯誤,好比認證請求失敗等。它有以下3個屬性。微信
code
:返回HTTP狀態碼,好比404表示網頁不存在,500表示服務器內部錯誤等。reason
:同父類同樣,用於返回錯誤的緣由。headers
:返回請求頭。下面咱們用幾個實例來看看:網絡
from urllib import request,error
try:
response = request.urlopen('http://cuiqingcai.com/index.htm')
except error.HTTPError as e:
print(e.reason, e.code, e.headers, seq='\n')
複製代碼
運行結果以下:socket
Not Found
404
Server: nginx/1.4.6 (Ubuntu)
Date: Wed, 03 Aug 2016 08:54:22 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: close
X-Powered-By: PHP/5.5.9-1ubuntu4.14
Vary: Cookie
Expires: Wed, 11 Jan 1984 05:00:00 GMT
Cache-Control: no-cache, must-revalidate, max-age=0
Pragma: no-cache
Link: <http://cuiqingcai.com/wp-json/>; rel="https://api.w.org/"
複製代碼
依然是一樣的網址,這裏捕獲了HTTPError
異常,輸出了reason
、code
和headers
屬性。
由於URLError
是HTTPError
的父類,因此能夠先選擇捕獲子類的錯誤,再去捕獲父類的錯誤,因此上述代碼更好的寫法以下:
from urllib import request, error
try:
response = request.urlopen('http://cuiqingcai.com/index.htm')
except error.HTTPError as e:
print(e.reason, e.code, e.headers, sep='\n')
except error.URLError as e:
print(e.reason)
else:
print('Request Successfully')
複製代碼
這樣就能夠作到先捕獲HTTPError
,獲取它的錯誤狀態碼、緣由、headers
等信息。若是不是HTTPError
異常,就會捕獲URLError
異常,輸出錯誤緣由。最後,用else
來處理正常的邏輯。這是一個較好的異常處理寫法。
有時候,reason
屬性返回的不必定是字符串,也多是一個對象。再看下面的實例:
import socket
import urllib.request
import urllib.error
try:
response = urllib.request.urlopen('https://www.baidu.com', timeout=0.01)
except urllib.error.URLError as e:
print(type(e.reason))
if isinstance(e.reason, socket.timeout):
print('TIME OUT')
複製代碼
這裏咱們直接設置超時時間來強制拋出timeout
異常。
運行結果以下:
<class 'socket.timeout'>
TIME OUT
複製代碼
能夠發現,reason
屬性的結果是socket.timeout
類。因此,這裏咱們能夠用isinstance()
方法來判斷它的類型,做出更詳細的異常判斷。
本節中,咱們講述了error
模塊的相關用法,經過合理地捕獲異常能夠作出更準確的異常判斷,使程序更加穩健。
本資源首發於崔慶才的我的博客靜覓: Python3網絡爬蟲開發實戰教程 | 靜覓
如想了解更多爬蟲資訊,請關注個人我的微信公衆號:進擊的Coder
weixin.qq.com/r/5zsjOyvEZ… (二維碼自動識別)