《零基础入门学习Python》第061讲:论一只爬虫的自我修养9:异常处理

高级语言的一个有些特性就是它可以从容不迫的处理每一个遇到的错误,不至于说遇到一个小错误就导致整个程序崩溃了,大部分高级语言处理错误的方法都是通过检测异常、处理异常来实现的,Python也是一样。

用程序用代码进行互联网访问的时候,会出现异常是再正常不过的了,例如之前实现了一个代理程序,通过十几个、几十个代理 ip 来实现爬虫访问,如果说其中一个代理 ip 突然不响应了,那就会报错,这种错误的触发率是极高的,全部 ip 你都可以使用那才是有鬼呢。但是,出现一个代理 ip 不能用并不会影响到整个脚本的任务,所以我们捕获此类的异常,处理它的方法只需要忽略它就可以了。

我们今天就来谈谈访问网页的异常处理。

当我们的 urlopen() 方法无法处理一个响应的时候,就会引发一个 URLError 的异常,通常在没有网络连接、或者对方服务器压根就不存在的时候,就会引发这个异常,同时,这个 URLError 的异常会同时伴随给一个 reason 属性,用于包含由错误编码和错误信息组成的元组。

我们举个例子感受一下:(我们尝试访问一个不存在的域名:http://www.cug123.edu.cn/)

(URLError 是包含在 urllib.error 模块里面的)

 
  
  1. >>> import urllib.request

  2. >>> import urllib.error

  3. >>> req = urllib.request.Request("http://www.cug123.edu.cn/")

  4. >>> try:

  5. urllib.request.urlopen(req)

  6. except urllib.error.URLError as e:

  7. print(e.reason)

  8. [Errno 11001] getaddrinfo failed

错误号是 11001,伴随的错误信息是 获取地址信息失败。(因为压根没有这个域名)

我们接下来看另一个,叫做 HTTPError

HTTPError 是 URLError  的一个子类,服务器上每一个 http 的响应都会返回一个数字的状态码,例如我们看到的 404(表示说东西已经不存在了),有时候状态码会指出服务器无法完成的请求类型,一般情况下,Python 会帮你处理一部分的这类请求,例如说响应一个 重定向,要求客户端从别的地方来获取文档,那么这个 urllib 模块就会自动帮你处理这个响应,但是,再有一些情况下,它是无法帮你处理的,例如我们刚才说的 404,是页面无法找到,它没办法帮你处理,需要你人工来进行过滤。也有 403(请求禁止),401(需要人工验证)。我们这里给大家准备好了 HTTP 的状态码大全。

我们当出现一个错误的时候,服务器就会返回一个 HTTP 错误号和错误的页面,你可以使用 HTTPError 实例对象作为页面返回的响应对象,它同样也拥有 read() 和 geturl() 或者说info() 这类方法,我们来感受一下:

 
  
  1. >>> import urllib.request

  2. >>> import urllib.error

  3. >>> req = urllib.request.Request("http://www.fishc.com/ooxx.html")

  4. >>> try:

  5. urllib.request.urlopen(req)

  6. except urllib.error.HTTPError as e:

  7. print(e.code)

  8. print(e.read())

  9. print(e.reason)

 运行结果如下:

 
  
  1. 404

  2. b'\r\n404 Not Found\r\n\r\n

    404 Not Found

    \r\n
    nginx
    \r\n\r\n\r\n'

  3. Not Found

最后给大家总结一下:

处理我们的异常有两种写法:

处理异常的第一种写法:

 
  
  1. from urllib.request import Request, urlopen

  2. from urllib.error import URLError, HTTPError

  3. req = Request(someurl)

  4. try:

  5. response = urlopen(req)

  6. except HTTPError as e:

  7. print('The server couldn\'t fulfill the request.')

  8. print('Error code: ', e.code)

  9. except URLError as e:

  10. print('We failed to reach a server.')

  11. print('Reason: ', e.reason)

  12. else:

  13. # everything is fine

注:这一种写法有一点需要注意的就是:except HTTPError 必须写在  except URLError 的前面,这样才会响应到  HTTPError ,因为 HTTPError是  URLError 的子类,如果 except URLError 写在前面,那么   except HTTPError  永远都响应不了。

处理异常的第二种写法:

 
  
  1. from urllib.request import Request, urlopen

  2. from urllib.error import URLError

  3. req = Request(someurl)

  4. try:

  5. response = urlopen(req)

  6. except URLError as e:

  7. if hasattr(e, 'reason'):

  8. print('We failed to reach a server.')

  9. print('Reason: ', e.reason)

  10. if hasattr(e, 'code'):

  11. print('The server couldn\'t fulfill the request.')

  12. print('Error code: ', e.code)

  13. else:

  14. # everything is fine

第二种方法就是 先看有没有错误(包括URLError 和 HTTPError ),只要有 其中一个,就会打印 reason, 然后继续判断是否有 code ,如果有 code,就是 HTTPError ,然后也把 code 打印出来。

举例说明:

(一)这是一个 URLError 的域名。http://www.cug123.edu.cn/

 
  
  1. >>> import urllib.request

  2. >>> import urllib.error

  3. >>> req = urllib.request.Request("http://www.cug123.edu.cn/")

  4. >>> try:

  5. urllib.request.urlopen(req)

  6. except urllib.error.URLError as e:

  7. if hasattr(e, 'reason'):

  8. print('Reason: ', e.reason)

  9. if hasattr(e, 'code'):

  10. print('Error code: ', e.code)

  11. Reason: [Errno 11001] getaddrinfo failed

(二)这是一个 HTTPError 的域名。http://www.fishc.com/ooxx.html

 
  
  1. >>> import urllib.request

  2. >>> import urllib.error

  3. >>> req = urllib.request.Request("http://www.fishc.com/ooxx.html")

  4. >>> try:

  5. urllib.request.urlopen(req)

  6. except urllib.error.URLError as e:

  7. if hasattr(e, 'reason'):

  8. print('Reason: ', e.reason)

  9. if hasattr(e, 'code'):

  10. print('Error code: ', e.code)

  11. Reason: Not Found

  12. Error code: 404

推荐使用第二种方法。

你可能感兴趣的:(python零基础,python)