爬虫基础 || 1.3 Handler辅助(验证,代理,cookies)

我们虽然可以构造请求,但是对于一些更高级的操作(比如 Cookies 处理、 代 理设置等),我们该怎么办呢?

接下来,就需要更强大的工具 Handler。

简而言之,我们可以把它理解为各种处理器,有专门处理登录验证的,有处理 Cookies 的,有处理代理设置的。 利用它们,我们几乎可以做到 HTTP 请求中所有的事情。

首先,介绍一下 urllib.request模块里的BaseHandler类,它是所有其他Handler的父类,它提供了最基本的方法,例如 default_open()、 protocol_request()等。

接下来,就有各种Handler子类继承这个BaseHandler类,举例如下。

HITPDefaultErrorHandler:用于处理HTTP 响应错误,错误都会抛出 HTTPError类型的异常。
HTTPRedirectHandler:用于处理重定向。
HTTPCookieProcessor: 用于处理 Cookies。
ProxyHandler:用于设置代理, 默认代理为空。
HTTPPasswordMgr:用于管理密码,它维护了用户名和密码的表。
HTTPBasicAuthHandler : 用于管理认证,如果一个链接打开时需要认证,那么可以用它来解决认证问题。

另外,还有其他的 Handler 类,这里就不一一列举了,详情可以参考官方文档: http//docs.python.org/3/library/urllib.request.html#urllib.request.BaseHandler。

另一个比较重要的类就是 OpenerDirector,我们可以称为 Opener。

之前用过 urlopen()这个方法,实际上它就是urllib为我们提供的一个Opener。

那么,为什么要引人 Opener 呢?因为需要实现更高级的功能。 之前使用的 Request 和 urlopen() 相当于类库为你封装好了极其常用的请求方法,利用它们可以完成基本的请求,但是现在不一样了, 我们需要实现更高级的功能,所以需要深入一层进行配置,使用更底层的实例来完成操作,所以这里 就用到了 Opener。

Opener 可以使用 open()方法,返回的类型和 urlopen()如出一辙。 那么,它和 Handler之间的关系就是利用 Handler 来构建 Opener。

1.验证

有些网站在打开时就会弹出提示框,直接提示你输入用户名和密码,验证成功后才能查看页面(虽然这种网站已经很少了)

from urllib.request import HTTPPasswordMgrWithDefaultRealm,HTTPBasicAuthHandler,build_opener
from urllib.error import URLError 

username = 'username'
password ='password'
url =  'http: //localhost:5000/'
p = HTTPPasswordMgrWithDefaultRealm() 
p.add_password(None, url, username, password)
auth_handler = HTTPBasicAuthHandler(p)
opener = build_opener(auth_handler) 
try: 
    result = opener.open(url) 
    html = result.read().decode('utf-8') 
    print(html) 
except URLError as e: 
    print(e.reason) 

解读代码:

得到的结果是 【  no hose given 】
1.这实例化HTTPBasicAuthHandler对象,其参数是HTTPPasswordMgrWithDefaultRealm对象,它利用 add_password()添加进去用户名和密码,这样就建立了一个处理验证的Handler。
2.接下来,利用这个 Handler 并使用 build_opener()方法构建一个 Opener,这个 Opener 在发送请求 时就相当于已经验证成功了。
3.接下来,利用 Opener 的 open()方法打开链接,就可以完成验证了。 这里获取到的结果就是验证 后的页面源码内容。

2.代理 

在做爬虫的时候,免不了要使用代理,如果要添加代理,可以使用Handler:

from urllib.error import URLError 
from urllib.request import ProxyHandler,build_opener 
proxy_handler = ProxyHandler({ 'http':'http://127.0.0.1:9743',
                               'https':'https://127.0.0.1:9743 '}) 
opener = build_opener(proxy_handler) 
try: 
    response = opener.open('https://www.baidu.com') 
    print(response.read() .decode('utf-8'))
except URLError as e: 
    print(e.reason) 

关于proxy_handler里的两个代理,没有自己的代理池的同学可以去西次代理网站去查找免费的代理,当然很多不能用,仅供学习使用,然后这里模拟的是:自己搭建了一个代理,它运行在 9743 端口上。 这里使用了 ProxyHandler,其参数是一个字典,键名是协议类型(比如 HTTP 或者 HTTPS 等), 键值是代理链接,可以添加多个代理。 然后,利用这个 Handler及 build_opener()方法构造一个 Opener,之后发送请求即可。

3.Cookies

cookies携带是爬虫中非常常用的一个手段,我们先直接使用Handler携带cookies,首先,我们必须声明一个 CookieJar 对象。 接下来,就需要利用 HTTPCookieProcessor 来构建一个 Handler,最后利用 build_opener()方法构建出 Opener,执行 open()函数即可。

import http.cookiejar,urllib.request 
cookie = http.cookiejar.CookieJar()
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler) 
response = opener.open('http://www.baidu.com') 
for item in cookie: 
    print(item.name+'='+item.value) 

那么,已经看到了cookies的输出结果,现在就把这个cookies储存到文本。

filename = 'cookies.txt' 
cookie = http.cookiejar.MozillaCookieJar(filename) 
handler = urllib.request.HTTPCookieProcessor(cookie) 
opener = urllib.request.build_opener(handler) 
response = opener.open('http://www.baidu.com') 
cookie.save(ignore_discard=True, ignore_expires=True) 

这时 CookieJar 就需要换成MozillaCookieJar,它在生成文件时会用到,是 CookieJar 的子类,可 以用来处理 Cookies 和文件相关的事件,比如读取和保存 Cookies,可以将 Cookies 保存成 Mozilla 型浏览器的Cookies格式。

另外, LWPCookieJar 同样可以读取和保存 Cookies,但是保存的格式和 MozillaCookieJar 不一样, 它会保存成 libwww-perl(LWP)格式的 Cookies 文件。 要保存成 LWP 格式的 Cookies 文件,可以在声明时就改为:

filename = 'cookies.txt' 
cookie = http.cookiejar.LWPCookieJar(filename)  ## 这里的声明改变
handler = urllib.request.HTTPCookieProcessor(cookie) 
opener = urllib.request.build_opener(handler) 
response = opener.open('http://www.baidu.com') 
cookie.save(ignore_discard=True, ignore_expires=True) 

两种cookies格式差异较大,现在我们从文件中读取cookies,以LWPCookieJar格式为例看一下:

cookie = http.cookiejar.LWPCookieJar() 
cookie.load('cookies.txt', ignore_discard=True, ignore_expires=True) 
handler = urllib.request.HTTPCookieProcessor(cookie) 
opener = urllib.request.build_opener(handler) 
response= opener.open('http://www.baidu.com')
print(response.read().decode('utf-8')) 

可以看到,这里调用 load()方法来读取本地的 Cookies 文件,获取到了 Cookies 的内容。

不过前 提是我们首先生成了LWPCookieJar格式的 Cookies,并保存成文件,然后读取 Cookies 之后使用同样 的方法构建 Handler和lOpener 即可完成操作。 运行结果正常的话,会输出百度网页的源代码。通过上面的方法,我们可以实现绝大多数请求功能的设置了。两种储存方式就格式不同,最终的使用效果是一样的。


本文主要参考《python3 网络爬虫开发实战》--崔庆才

发布了17 篇原创文章 · 获赞 12 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Watson_Ashin/article/details/104295153
1.3