Python3網絡爬蟲實戰---2一、使用Urllib:處理異常

上一篇文章: Python3網絡爬蟲實戰---20、使用Urllib:發送請求
下一篇文章:

在前面一節咱們瞭解了 Request 的發送過程,可是在網絡狀況很差的狀況下,出現了異常怎麼辦呢?這時若是咱們不處理這些異常,程序極可能報錯而終止運行,因此異常處理仍是十分有必要的。html

Urllib 的 error 模塊定義了由 request 模塊產生的異常。若是出現了問題,request 模塊便會拋出 error 模塊中定義的異常,本節會對其進行詳細的介紹。nginx

1. URLError

URLError 類來自 Urllib 庫的 error 模塊,它繼承自 OSError 類,是 error 異常模塊的基類,由 request 模塊生的異常均可以經過捕獲這個類來處理。segmentfault

它具備一個屬性 reason,即返回錯誤的緣由。服務器

下面用一個實例來感覺一下:網絡

from urllib import request, error
try:
    response = request.urlopen('http://cuiqingcai.com/index.htm')
except error.URLError as e:
    print(e.reason)

咱們打開一個不存在的頁面,照理來講應該會報錯,可是這時咱們捕獲了 URLError 這個異常,運行結果以下:socket

Not Found

程序沒有直接報錯,而是輸出瞭如上內容,這樣經過如上操做,咱們就能夠避免程序異常終止,同時異常獲得了有效處理。ui

2. HTTPError

它是 URLError 的子類,專門用來處理 HTTP 請求錯誤,好比認證請求失敗等等。url

它有三個屬性。code

  • code,返回 HTTP Status Code,即狀態碼,好比 404 網頁不存在,500 服務器內部錯誤等等。
  • reason,同父類同樣,返回錯誤的緣由。
  • headers,返回 Request Headers。

下面咱們來用幾個實例感覺一下:htm

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')

運行結果:

Not Found
404
Date: Mon, 17 Jun 2019 04:52:50 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: close
Vary: Accept-Encoding
Status: 404 Not Found
Cache-Control: no-cache
Strict-Transport-Security: max-age=31536000
X-XSS-Protection: 1; mode=block
X-Request-Id: e65fb029-a4fd-46e2-91c3-9616ccc2f879
X-Runtime: 0.006814
X-Frame-Options: SAMEORIGIN
X-Content-Type-Options: nosniff
X-Powered-By: Phusion Passenger 6.0.2
Server: nginx + Phusion Passenger 6.0.2

依然是一樣的網址,在這裏咱們捕獲了 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() 方法來判斷它的類型,作出更詳細的異常判斷。

3. 結語

本節講述了 error 模塊的相關用法,經過合理地捕獲異常能夠作出更準確的異常判斷,使得程序更佳穩健。

相關文章
相關標籤/搜索