Handler处理器和自定义opener
在我们使用urllib库请求是都是使用urlopen()方法实现的。实际上它的底层是使用HTTPHandler个Opener来实现的。如:urlopen()源码:
global _opener
if cafile or capath or cadefault:
...
https_handler = HTTPSHandler(context=context)
opener = build_opener(https_handler)
elif context:
https_handler = HTTPSHandler(context=context)
opener = build_opener(https_handler)
elif _opener is None:
_opener = opener = build_opener()
else:
opener = _opener
return opener.open(url, data, timeout)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
我们采用urlopen()的方式去请求,其实是有些局限性的,比如我们需要打开debug模式,或通过代理模式去请求,就不行了。如果要实现debug模式或代理请求的话,我们需要自己定义Handler和opener。
在urllib库中,给我们提供了一些Handler,如:HTTPHandler,HTTPSHandler,ProxyHandler,BaseHandler,AbstractHTTPHandler,FileHandler,FTPHandler,分别用于处理HTTP,HTTPS,Proxy代理等。
简单的自定义Handler和opener
import urllib.request
def common_handler(url, headers):
"""
通过使用HTTPHandler发送请求
"""
# 创建HTTPHandler对象
handlers = urllib.request.HTTPHandler()
# 创建一个Opener对象
opener = urllib.request.build_opener(handlers)
# 获取一个请求
req = urllib.request.Request(url, headers=headers)
# 通过opener请求访问服务器,并返回一个响应对象
resp = opener.open(req)
with open('common_handler_baidu.html', 'wb') as f:
f.write(resp.read())
if __name__ == '__main__':
url = 'http://www.baidu.com'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.62 Safari/537.36'}
common_handler(url, headers)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
HTTPHandler的debug模式
HTTPHandler的debug模式,是通过在HTTPHandler的参数中传入debuglevel=1,1表示打开debug模式。0表示关闭,默认是0。代码如下:
import urllib.request
def debug_handler(url, headers):
# 给HTTPHandler的构造方法中,添加有个参数,debuglevel=1,表示打开debug模式。
handlers = urllib.request.HTTPHandler(debuglevel=1)
opener = urllib.request.build_opener(handlers)
req = urllib.request.Request(url, headers=headers)
resp = opener.open(req)
with open('debug_handler_baidu.html', 'wb') as f:
f.write(resp.read())
if __name__ == '__main__':
url = 'http://www.baidu.com'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.62 Safari/537.36'}
debug_handler(url, headers)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
在运行的时候,会直接输入log信息。如图:
ProxyHandler的代理模式
在urllib库中,我们使用ProxyHandler来进行代理请求。具体代码如下:
import urllib.request
def proxy_hander(url, headers):
# 通过ProxyHandler来做代理请求,参数是一个dict类型。key是http,value是指ip和端口。
handlers = urllib.request.ProxyHandler({'http': '124.88.67.81:80'}) # ip是网上查找的公共ip,有可能失效,不能访问
opener = urllib.request.build_opener(handlers)
req = urllib.request.Request(url, headers=headers)
resp = opener.open(req)
with open('proxy_handler_baidu.html', 'wb') as f:
f.write(resp.read())
if __name__ == '__main__':
url = 'http://www.baidu.com'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.62 Safari/537.36'}
proxy_hander(url, headers)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
ProxyBasicAuthHandler代理授权验证
如果我们是使用一个需要授权验证的ip做代理,直接使用ProxyHandler代理会报一个HTTP 407的错误,如下:
HTTPError: HTTP Error 407: Proxy Authentication Required
1
遇到上述问题,我们需要ProxyBasicAuthHandler来处理代理请求。除此之外,我们还需要HTTPPasswordMgrWithDefaultRealm构建一个密码的管理对象,保存需要处理的用户名和密码。具体看下面示例:
import urllib.request
def proxyauth_handler(url, headers):
# 代理的ip和端口
server_ip = '192.168.199.107:80' # 在测试是,请更换代理的ip,该ip已失效
# 代理ip的用户名,如 admin
user = 'admin'
# 代理ip密码,如 admin
password = 'admin'
# 创建一个密码管理对象
passwordMgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
# 将ip,用户名,密码保存到密码管理器中
# 第一个参数realm是与远程服务器相关的域信息,一般没人管它都是写None
passwordMgr.add_password(None, server_ip, user, password)
# 获取ProxyBasicAuthHandler对象
handler = urllib.request.ProxyBasicAuthHandler(passwordMgr)
# 获取opener对象
opener = urllib.request.build_opener(handler)
# 获取请求对象
req = urllib.request.Request(url, headers=headers)
# 通过opener请求服务器,获取一个响应对象
resp = opener.open(req)
with open('proxyauth_handler_baidu.html', 'wb') as f:
f.write(resp.read())
if __name__ == '__main__':
url = 'http://www.baidu.com'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.62 Safari/537.36'}
auth_proxy_handler(url, headers)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
HTTPBasicAuthHandler处理器(web客户端授权)
有些web服务器在访问时,需要进行用户身份验证,爬虫直接访问会报出HTTP 401错误,表示访问身份没有授权。
HTTPError: HTTP Eeeor 401: Unauthorized
1
对于这种情况,我们可以通过HTTPBasicAuthHandler处理器来处理。
HTTPBasicAuthHandler处理器和ProxyBasicAuthHandler处理器的用法是一样的,也是通过ip(或url),用户名,密码,通过密码管理对象保存,通过HTTPBasicAuthHandler返回opener对象。
具体代码如下:
import urllib.request
def httpauth_handler(url, headers):
# 授权账户用户名
user = 'admin'
# 授权账户密码
password = 'admin'
# 获取密码管理者对象
passwordMgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
# 将密码保存到密码管理者
passwordMgr.add_password(None, url, user, password)
# 将密码管理者传给HTTPBasicAuthHandler处理器处理,返回一个处理器对象
handler = urllib.request.HTTPBasicAuthHandler(passwordMgr)
# 传入handler,构建一个opener对象
opener = urllib.request.build_opener(handler)
# 获取一个请求对象
req = urllib.request.Request(url, headers=headers)
# 通过opener请求服务器,获取响应对象
resp = opener.open(req)
# 将响应对象返回的是数据读取到文件
with open('httpauth_handler.html', 'wb') as f:
f.write(resp.read())
if __name__ == '__main__':
url = 'http://www.baidu.com'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.62 Safari/537.36'}
httpauth_handler(url, headers)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
备注:如果我们急需要web客户端验证,有需要代理,那怎么办。实际上build_open()方法,可以传递多个handler对象。实现多个handler的处理需要。
---------------------
【转载,仅作分享,侵删】
作者:张行之
来源:CSDN
原文:https://blog.csdn.net/qq_33689414/article/details/78553450
版权声明:本文为博主原创文章,转载请附上博文链接!
|
|