小白學 Python 爬蟲(13):urllib 基礎使用(三)
人生苦短,我用 Python
前文傳送門:
小白學 Python 爬蟲(1):開篇
小白學 Python 爬蟲(2):前置準備(一)基本類庫的安裝
小白學 Python 爬蟲(3):前置準備(二)Linux基礎入門
小白學 Python 爬蟲(4):前置準備(三)Docker基礎入門
小白學 Python 爬蟲(5):前置準備(四)資料庫基礎
小白學 Python 爬蟲(6):前置準備(五)爬蟲框架的安裝
小白學 Python 爬蟲(7):HTTP 基礎
小白學 Python 爬蟲(8):網頁基礎
小白學 Python 爬蟲(9):爬蟲基礎
小白學 Python 爬蟲(10):Session 和 Cookies
小白學 Python 爬蟲(11):urllib 基礎使用(一)
小白學 Python 爬蟲(12):urllib 基礎使用(二)
引言
前面兩篇基礎,我們介紹請求傳送的過程。
不知道各位同學有沒有想過這樣一個問題,如果在爬蟲執行的過程中,網路突然波動了下,比如突然網速很慢很慢,造成當前的請求超時,程式很可能會直接掛掉。
這種處理方式顯然不是我們希望看到的,我們希望看到的肯定是如果當前的請求掛掉,那就掛掉,不要影響其他的請求或者是下一次的請求。
那麼,我們在傳送請求的時候,異常處理就顯得十分有必要。
urllib 的 error 模組定義了由 request 模組產生的異常,如果出現問題, request 模組便會丟擲 error 模組中定義的異常。
URLError
URLError 這個類來自於 urllib 庫的 error 模組,它繼承自 OSError ,是 error 異常模組的基類,由 request 模組產生的異常都可以通過捕獲這個類來處理。
它只有一個屬性 reason ,即返回錯誤的原因。
我們來寫一個簡單的示例大家看一下:
from urllib import request, error # 訪問明顯不存在的地址,報錯:Not Found try: response = request.urlopen('https://www.geekdigging.com/aa') except error.URLError as e: print(e.reason) # 訪問超時,報錯:timed out try: response = request.urlopen('https://www.baidu.com', timeout=0.001) except error.URLError as e: print(e.reason)
這裡我們訪問了一個明顯不存在的連結和限定了極短的超時時間,這裡會丟擲異常,但是我們捕獲了 URLError 這個異常,執行結果如下:
Not Found
timed out
程式沒有直接丟擲異常終止執行,而是輸出了上面這個異常,通過這樣的操作,我們可以避免程式異常終止,同時還可以對這個異常做出針對性的處理。
此外,異常捕捉丟擲的異常不一定都是字串型別,比如訪問超時的報錯,我們將列印結果的程式碼稍作改動:
from urllib import request, error
import socket
# 異常型別示例
try:
response = request.urlopen('https://www.baidu.com', timeout=0.001)
except error.URLError as e:
print(type(e.reason))
if isinstance(e.reason, socket.timeout):
print('TIME OUT')
結果如下:
<class 'socket.timeout'>
TIME OUT
HTTPError
它是 URLError 的子類,專門用來處理 HTTP 請求錯誤,比如認證請求失敗等。它有如下 3 個屬性。
- code:返回HTTP狀態碼,比如404表示網頁不存在,500表示伺服器內部錯誤等。
- reason:同父類一樣,用於返回錯誤的原因。
- headers:返回請求頭。
還是先看一個最簡單的示例:
from urllib import request, error
# 訪問明顯不存在的地址,使用 HTTPError 捕捉異常
try:
response = request.urlopen('https://www.geekdigging.com/aa')
except error.HTTPError as e:
print(e.reason, e.code, e.headers, sep='\n')
執行結果如下:
Not Found
404
Date: Sun, 01 Dec 2019 15:11:48 GMT
Content-Type: text/html
Content-Length: 49307
Connection: close
Server: tencent-cos
Last-Modified: Sun, 01 Dec 2019 15:03:24 GMT
X-NWS-UUID-VERIFY: c89959eb27b89a0fb1c0326d1b2e7171
Accept-Ranges: bytes
ETag: "1bb6cc2c28a5621cf0c3238107edc229"
x-cos-error-code: NoSuchKey
x-cos-error-detail-Key: aa
x-cos-error-message: The specified key does not exist.
x-cos-request-id: NWRlM2Q4MzRfMzNhNzAzMDlfYTljZl8yNGU1NTgx
x-cos-trace-id: OGVmYzZiMmQzYjA2OWNhODk0NTRkMTBiOWVmMDAxODc0OWRkZjk0ZDM1NmI1M2E2MTRlY2MzZDhmNmI5MWI1OTQ5YWUxMjNkYTk3NzdjZmZlMDQzOTgxOThkOTNlOWFkOGJiN2YzOGQ5MDdjNGY0ODQ1MGIzYjUyMzg2NjFhNzc=
X-Daa-Tunnel: hop_count=2
X-NWS-LOG-UUID: 7c3fe80b-af9a-4e59-969b-10c8b3963a1d
X-Cache-Lookup: Hit From Upstream
X-Cache-Lookup: Hit From Upstream
因為 URLError 是 HTTPError 的父類,所以可以先選擇捕獲子類的錯誤,再去捕獲父類的錯誤,這樣對異常的處理更具針對性。
注意: 捕捉異常一般先捕捉子類異常,再捕捉父類異常。
所以我們可以更改下前面的異常捕捉的程式碼進行一些優化:
# 優化異常捕捉程式碼
try:
response = request.urlopen('https://www.geekdigging.com/aa')
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 Success!')
示例程式碼
本系列的所有程式碼小編都會放在程式碼管理倉庫 Github 和 Gitee 上,方便大家取用。
示例程式碼-Github
示例程式碼-Gitee
參考
https://www.cnblogs.com/zhangxinqi/p/9170312.h