urlib常见异常处理与url解析

一.urlib异常处理

1、URLError异常

通常引起URLError的原因是:无网络连接(没有到目标服务器的路由)、访问的目标服务器不存在。在这种情况下,异常对象会有reason属性(是一个(错误码、错误原因)的元组)

1)访问成功时:

from urllib import  request, error
try:
    url = 'https://www.baidu.com/hello.html'
    response = request.urlopen(url)
    print(response.read().decode('utf-8'))
except error.HTTPError as e:
    print(e.reason, e.code, e.headers, sep='\n')
except error.URLError as e:
    print(e.reason)
else:
    print("成功")

我们可以成功的访问到百度页面
在这里插入图片描述

2)有异常时

from urllib import  request, error

url = 'https://www.baidu.com/hello.html'
response = request.urlopen(url)
print(response.read().decode('utf-8'))

这里我断开了网络,出现了URLError
在这里插入图片描述

2、HTTPError

每一个从服务器返回的HTTP响应都有一个状态码。其中,有的状态码表示服务器不能完成相应的请求,默认的处理程序可以为我们处理一些这样的状态码(如返回的响应是重定向,urllib2会自动为我们从重定向后的页面中获取信息)。有些状态码,urllib2模块不能帮我们处理,那么urlopen函数就会引起HTTPError异常,其中典型的有404/401

  ##因为URLError是HTTPError的父类,所以在捕获异常的时候可以先找子类是否异常,如果子类找不到,再找父类即可
from urllib import  request, error
try:
    url = 'http://www.douban.com/hello89.html'
    response = request.urlopen(url)
    print(response.read().decode('utf-8'))
except error.HTTPError as e:
    print(e.reason, e.code, e.headers, sep='\n')
except error.URLError as e:
    print(e.reason)
else:
    print("成功")

上例是我访问一个豆瓣不存在的网页
在这里插入图片描述

常见状态返回码

 100:继续 客户端应当继续发送请求。客户端应当继续发送请求的剩余部分,或者如果请求已经完成,忽略这个响应。
 101: 转换协议 在发送完这个响应最后的空行后,服务器将会切换到在Upgrade 消息头中定义的那些协议。只有在切换新的协议更有好处的时候才应该采取类似措施。 
 102:继续处理 由WebDAV(RFC 2518)扩展的状态码,代表处理将被继续执行。 
 200:请求成功 处理方式:获得响应的内容,进行处理 201:请求完成,结果是创建了新资源。新创建资源的URI可在响应的实体中得到 处理方式:爬虫中不会遇到 
 202:请求被接受,但处理尚未完成 处理方式:阻塞等待 
 204:服务器端已经实现了请求,但是没有返回新的信 息。如果客户是用户代理,则无须为此更新自身的文档视图。 处理方式:丢弃 
 300:该状态码不被HTTP/1.0的应用程序直接使用, 只是作为3XX类型回应的默认解释。存在多个可用的被请求资源。 处理方式:若程序中能够处理,则进行进一步处理,如果程序中不能处理,则丢弃 
 301:请求到的资源都会分配一个永久的URL,这样就可以在将来通过该URL来访问此资源 处理方式:重定向到分配的URL 
 302:请求到的资源在一个不同的URL处临时保存 处理方式:重定向到临时的URL 
 304:请求的资源未更新 处理方式:丢弃 400:非法请求 处理方式:丢弃 
 401:未授权 处理方式:丢弃 
 403:禁止 处理方式:丢弃 
 404:没有找到 处理方式:丢弃
 500:服务器内部错误 服务器遇到了一个未曾预料的状况,导致了它无法完成对请求的处理。一般来说,这个问题都会在服务器端的源代码出现错误时出现。 
 501:服务器无法识别 服务器不支持当前请求所需要的某个功能。当服务器无法识别请求的方法,并且无法支持其对任何资源的请求。 
 502:错误网关 作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应。 
 503:服务出错 由于临时的服务器维护或者过载,服务器当前无法处理请求。这个状况是临时的,并且将在一段时间以后恢复。

3、超时异常处理

为了捕获超时异常,我在这里设置了时间限制,当响应超过0.01s时,就会认为超时。
from urllib import request, error
import socket

try:
    url = 'https://www.baidu.com'
    response = request.urlopen(url, timeout=0.01)
    print(response.read().decode('utf-8'))
except error.HTTPError as e:
    print(e.reason, e.code, e.headers, sep='\n')
except error.URLError as e:
    print(e.reason)
    if isinstance(e.reason, socket.timeout):
        print("超时")
else:
    print("成功")

在这里插入图片描述

二.urlib解析

'https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=0&rsv_idx=1&tn=baidu&wd=hello&rsv_pq=d0f841b10001fab6&rsv_t=2d43603JgfgVkvPtTiNX%2FIYssE6lWfmSKxVCtgi0Ix5w1mnjks2eEMG%2F0Gw&rqlang=cn&rsv_enter=1&rsv_sug3=6&rsv_sug1=4&rsv_sug7=101&rsv_sug2=0&inputT=838&rsv_sug4=1460'

一般一个完整的url地址包括以下部分:

1.协议部分(scheme):该URL的协议部分为“https:”,这代表网页使用的是HTTP协议。在Internet中可以使用多种协议,如HTTP,FTP等等本例中使用的是HTTP协议。

2.域名+端口部分(netloc):该URL的域名部分为“www.baidu.com”。一个URL中,也可以使用IP地址作为域名使用。跟在域名后面的是端口,域名和端口之间使用“:”作为分隔符。端口不是一个URL必须的部分,如果省略端口部分,将采用默认端口(这里没显示端口,所以采用了默认端口)

3.虚拟目录部分(path):从域名后的第一个“/”开始到最后一个“/“为止,是虚拟目录部分。虚拟目录也不是一个URL必须的部分。本例中的虚拟目录是path=’/s’

4.文件名部分(params):从域名后的最后一个“/”开始到“?”为止,是文件名部分,如果没有“?”,则是从域名后的最后一个“/”开始到“#”为止,是文件部分,如果没有“?”和“#”,那么从域名后的最后一个“/”开始到结束,都是文件名部分。本例中没有文件名。文件名部分也不是一个URL必须的部分,如果省略该部分,则使用默认的文件名

5.锚部分(fragment):从“#”开始到最后,都是锚部分。本例中没有锚部分。锚部分也不是一个URL必须的部分

6.参数部分(query):从“?”开始到“#”为止之间的部分为参数部分,又称搜索部分、查询部分。本例中的参数部分为“ie=utf-8&f=8&rsv_bp=0&rsv_idx=1&tn=baidu&wd=hello&rsv_pq=d0f841b10001fab6&rsv_t=2d43603JgfgVkvPtTiNX%2FIYssE6lWfmSKxVCtgi0Ix5w1mnjks2eEMG%2F0Gw&rqlang=cn&rsv_enter=1&rsv_sug3=6&rsv_sug1=4&rsv_sug7=101&rsv_sug2=0&inputT=838&rsv_sug4=1460’”。参数可以允许有多个参数,参数与参数之间用“&”作为分隔符。

代码实现对url的解析

这里我们要调用urllib模块中的parse类,再通过parse.urlparse构造一个实例化对象。即可进行解析。
from urllib import parse

url = 'https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=0&rsv_idx=1&tn=baidu&wd=hello&rsv_pq=d0f841b10001fab6&rsv_t=2d43603JgfgVkvPtTiNX%2FIYssE6lWfmSKxVCtgi0Ix5w1mnjks2eEMG%2F0Gw&rqlang=cn&rsv_enter=1&rsv_sug3=6&rsv_sug1=4&rsv_sug7=101&rsv_sug2=0&inputT=838&rsv_sug4=1460'

parsed_tuple = parse.urlparse(url)
print(parsed_tuple)
print(parsed_tuple.scheme)
print(parsed_tuple.netloc)
print(parsed_tuple.path)
print(parsed_tuple.params)
print(parsed_tuple.query)
print(parsed_tuple.fragment)

在这里插入图片描述

通过字典编码的方式构造url地址

这里我们要用到urlencode方法

from urllib.parse import   urlencode     
params = {
    'name':'westos',
    'age':20
}
base_url = 'http://www.baidu.com?'
url = base_url + urlencode(params)   ###将域名与文件名联结起来构成新的url
print(url)

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/forever_wen/article/details/83104949