Python3 模块2之 Urllib之 urllib.error

紧接上一篇:Python3模块1之Urllib之 urllib.request

urllib.error

urllib.error模块定义由urllib.request引发的异常类。URLError 为基本的异常类。异常处理主要用到两个类,urllib.error.URLErrorurllib.error.HTTPError

一. URLError

URLError 是 urrlib.error 异常类的基类,具有 reason属性,返回错误原因。可以捕获由 urllib.request 产生的异常。

常常产生 URLError 的原因可能有

  • 服务器连接失败
  • 服务器不存在
  • 远程 URL 地址不存在
  • 触发了 HTTPError

下面是例1—-远程地址不存在

from urllib import request, error
try:
    response = request.urlopen('http://blog.csdn.net/qq_36148849.html')
except error.URLError as e:
    print(e.reason)

输出结果1

Not Found

实例1中,爬取的网页本身不存在。通过 urllib.error.URLError as e 捕获异常信息 e,然后对其进行相应的异常处理,并输出异常原因。

下面是例2—-触发HTTPError

import urllib.request
import urllib.error
try:
    req=urllib.request.urlopen('http://www.dianping.com/')
    print(req.read())
except urllib.error.URLError as e:
    print('code: ',e.code)
    print('reason: ',e.reason)

输出结果2

code:  403
reason:  Forbidden

下面是例3—-远程服务器不存在

from urllib import request, error
try:
    response = request.urlopen('http://blog.baidu.net/')
except error.URLError as e:
    print(e.reason)

输出3

[Errno 11001] getaddrinfo failed

下面是例4—-远程服务器连接不上

import urllib.request
import urllib.error
url = "http://www.google.com"
try:
    response =  urllib.request.urlopen(url)
except urllib.error.URLError as e:
    print(e.reason)

输出4

[WinError 10060] 由于连接方在一段时间后没有正确答复或连接的主机没有反应,连接尝试失败。

其中,实例2中,对大众点评官网进行爬取,大众点评有反爬虫机制,没有设置参数头模拟浏览器访问,会导致返回 403 错误,同时 URLError 进行异常信息捕获并输出对应的异常状态和异常原因。在这种情况下是触发了 HTTPError ,故如上异常处理可以直接使用 HTTPError 代替 URLError(如下)。

URLError 改为 HTTPError

import urllib.request
import urllib.error
try:
    req=urllib.request.urlopen('http://www.dianping.com/')
    print(req.read())
except urllib.error.HTTPError as e:
    print('code: ',e.code)
    print('reason: ',e.reason)

二. HTTPError

HTTPError 是 URLError 的子类,专门处理 HTTP 和 HTTPS 请求错误。HTTPError 并不能处理父类支持的异常处理。

HTTPError 具有三个属性

  • code:HTTP/HTTPS 请求返回的状态码。
  • headers:HTTP 请求返回的响应头信息。
  • reason:与父类方法一样,表示返回错误原因。

下面是获取 HTTP 异常的实例

from urllib import request, error
try:
    response = request.urlopen('https://www.douban.com/w_linuxsaidfefefe')
except error.HTTPError as e:
    print('reason: ',e.reason)
    print('reason: ',e.code)

输出

reason:  Not Found
reason:  404

由于页面 https://www.douban.com/w_linuxsaidfefefe 根本不存在,相应输出 404 错误信息。

关于 URLError 和 HTTPError 的关系

  • 由于 HTTPError 是 URLError 的子类,所以在调用 URLError 进行异常处理时,一般先在 子类找是否出现 HTTP 错误,然后再执行父类的异常处理。
  • 父类 URLError 并不能完全替代子类 HTTPError ,子类也不能实现父类所有异常处理功能。

对于第二点,可以做以下的实例分析

from urllib import request, error
try:
    response = request.urlopen('https://www.douban_baidu.com')
except error.URLError as e:
    print('reason: ',e.reason)

输出

reason:  [Errno 11001] getaddrinfo failed

对于远程服务器不存在的情况下,如果不使用 URLError 而使用 HTTPError,即用 HTTPError 替代 URLError :

try:
    response = request.urlopen('https://www.douban_baidu.com')
except error.HTTPError as e:
    print('reason: ',e.reason)

此时,查看输出可知,这时候 HTTPError 并不能正常捕获异常信息。即可见 HTTPError 并不能完全替代 URLError
那么竟然这样,父类 URLError 能否完全替代 子类 HTTPError 呢?貌似可行? 先看下面一个实例。

这是一个测试实例

from urllib import request, error
try:
    response = request.urlopen('https://www.douban_baidu.com')
except error.URLError as e:
    print('reason: ',e.reason)
    print('code ',e.code)

很明显,这里出现了错误 AttributeError: 'URLError' object has no attribute 'code' , 原因是这里的异常并不是属于子类能够处理的异常,也就是说这里并没有调用子类,实现的父类处理异常,而父类并没有code 属性。也就是说,如果你只需要得到的是异常原因 e.reason ,父类 URLError 是可以完全替代子类HTTPError 的。但如果你想既能够成功处理异常,又想知道是否为 HTTPError 异常,并能够得到异常状态码 code 的情况下。就不具有替换性可言了。

那么,问题来了,日常使用过程中并不能预测异常类型,所以,最好的办法是同时实现两种检测。

try-except 的办法可以很好同时兼容两种异常处理:

from urllib import request, error

try:
    response = request.urlopen('http://blog.csdn.net/qq_36148849.html')
except error.HTTPError as e:
    print('HTTPError 异常错误 ')
    print('reason:'+str(e.reason), 'code:'+str(e.code), 'headers:'+str(e.headers), sep='\n')
except error.URLError as e:
    print('URLError 异常错误 ')
    print('reason:'+str(e.reason))
else:
    print('Request Successfully')

输出

HTTPError 异常错误 
reason:Not Found
code:404
headers:Server: openresty
Date: Wed, 24 Jan 2018 06:29:34 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 4144
Connection: close
Vary: Accept-Encoding
Set-Cookie: uuid_tt_dd=10_20054827090-1516775374087-920214; Expires=Thu, 01 Jan 2025 00:00:00 GMT; Path=/; Domain=.csdn.net;
Set-Cookie: dc_session_id=10_1516775374087.761530; Expires=Thu, 01 Jan 2025 00:00:00 GMT; Path=/; Domain=.csdn.net;
ETag: "5a324c7d-1030"

当然,这里有一个更为简便的处理异常的方式。
下面是整合异常处理的实现例子

try:
    response = request.urlopen('https://www.douban_baidu.com')
except error.URLError as e:
    if hasattr(e,"code"):
        print('reason: ',e.code)
    if hasattr(e,"reason"):
        print('reason: ',e.reason)

hasattr() 函数用于判断某类是否具有此属性。

三.其他常用异常处理

超时异常处理

下面是一个实例

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

输出

'socket.timeout'>
TIME OUT

备注

学习资料: python doc

你可能感兴趣的:(爬虫,python,python,库)