紧接上一篇:Python3模块1之Urllib之 urllib.request
urllib.error模块定义由urllib.request引发的异常类。URLError 为基本的异常类。异常处理主要用到两个类,
urllib.error.URLError
和urllib.error.HTTPError
。
URLError 是 urrlib.error 异常类的基类,具有 reason
属性,返回错误原因。可以捕获由 urllib.request 产生的异常。
常常产生 URLError 的原因可能有:
下面是例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 是 URLError 的子类,专门处理 HTTP 和 HTTPS 请求错误。HTTPError 并不能处理父类支持的异常处理。
HTTPError 具有三个属性:
下面是获取 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 的关系:
对于第二点,可以做以下的实例分析:
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