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 模块的相关用法,经过合理地捕获异常能够作出更准确的异常判断,使得程序更佳稳健。

相关文章
相关标签/搜索