【Python从入门到进阶】27、Handler处理器使用及代理和Cookie登录实现

接上篇《26、urllib的异常处理》
上一篇我们讲解了urllib的异常处理机制。本篇我们来讲解urllib中Handler处理器的基本使用。

一、Handler处理器的作用和功能

在Python的urllib库中,Handler处理器是一个关键的组件,它提供了处理不同协议和功能的网络请求和响应的灵活性和可扩展性。

1、支持不同协议:Handler处理器可以根据URL的协议来选择合适的处理器,例如HTTP、HTTPS、FTP等。这使得我们能够通过同一套接口处理多种不同协议的网络请求。

2、处理请求和响应:通过Handler处理器,我们可以发送各种类型的请求,如GET请求、POST请求等,并处理服务器返回的响应数据。它提供了发送请求和接收响应的方法,以及对请求和响应进行自定义修改和解析的能力。

3、处理特定任务:Handler处理器可以专注于特定的任务和功能。例如,HTTPHandler处理器用于处理HTTP请求和响应,包括建立连接、发送请求、接收响应、处理重定向和处理cookie等。其他处理器如HTTPSHandler处理器用于处理HTTPS请求的安全连接,FileHandler处理器用于下载文件等。

4、可扩展性:Handler处理器的设计允许我们编写自定义的处理器,以满足特定的需求。通过继承基类BaseHandler,我们可以实现自定义的处理器,并将其与其他处理器组合使用,以扩展urllib库的功能。

5、处理器栈:Handler处理器可以按照一定的顺序进行组合和堆叠,形成处理器栈。处理器栈中的处理器按照添加的顺序依次进行调用,直到找到适合处理请求的处理器。这种层级结构使得处理器能够协同工作,并根据具体的场景选择合适的处理器来处理请求。

通过使用Handler处理器,我们可以更加灵活地进行网络编程和请求处理。它使得我们能够以统一、可扩展和易于维护的方式处理不同协议和功能的网络请求和响应,为开发网络应用提供了方便的工具和接口。

二、Handler和urlopen函数对比

之前,我们一直使用urllib.request.urlopen(url)的方式来请求网站,而其实它是一个特殊的opener(request模块自动帮我们创建的),opener是urllib2.OpenerDirectory的实例。
但是,基本的urlopen()方法不支持代理、cookie等其他的HTTP/HTTPS高级功能,需要有功能更加强大的Handler处理器来弥补这些空缺。
相对于urlopen函数,Handler具有以下优势:
【Python从入门到进阶】27、Handler处理器使用及代理和Cookie登录实现_第1张图片

1、Handler的优势

(1)灵活性和可扩展性:Handler提供了处理不同协议和功能的灵活性和可扩展性。通过选择合适的处理器,我们可以处理多种不同协议的请求,并根据需要自定义修改请求和解析响应。
(2)处理器栈的组合:Handler允许将不同类型的处理器按照一定的顺序组合在一起,形成处理器栈。这使得我们能够根据需求将多个处理器协同工作,并确保请求被正确处理。
(3)更多高级功能:Handler提供了额外的高级功能,如处理重定向、代理访问、管理cookie、建立安全连接等。它们为网络请求提供了更多的控制和功能。
(4)自定义处理器的能力:通过继承BaseHandler类,我们可以编写自定义的处理器来满足特定的需求。这使得我们能够以统一的方式扩展和定制网络请求的处理,满足复杂的应用场景。
(5)细粒度的配置:使用Handler,我们可以对请求进行更细粒度的控制和配置。例如,我们可以添加自定义的请求头、修改请求参数、设置代理等。

2、urlopen的缺点

(1)无法灵活地处理不同协议和功能:urlopen函数在处理网络请求时,对于不同协议和特定功能的支持有限。它更适合简单的GET请求,无法提供处理器栈和自定义处理器等高级功能。
(2)限制较少的控制选项:urlopen函数提供了一些基本的请求参数设置,但没有Handler那样细粒度的配置能力。这使得它难以满足更复杂的网络编程需求。
(3)缺少对高级功能的直接支持:相对于Handler,urlopen没有直接支持处理重定向、管理cookie、建立安全连接等高级功能。如果要使用这些功能,可能需要额外的处理步骤或代码。
总结而言,Handler具有更高级、更灵活和更可扩展的方式来处理网络请求和响应。它提供了更多的控制选项、高级功能和自定义能力,适用于复杂的网络编程场景。相比之下,urlopen函数适合简单的请求,缺乏灵活性和高级功能的支持。

三、Handler处理器的角色和工作方式

在Python的urllib库中,Handler处理器扮演着关键的角色。它充当了一个中间人,负责处理与不同协议和功能相关的网络请求和响应的细节。

Handler处理器的作用是根据请求的类型、URL的协议以及其他条件,选择适当的处理器来处理请求。每个处理器都专注于一种特定的任务,例如处理HTTP请求、处理HTTPS请求、处理文件下载等。通过使用不同的处理器,我们可以轻松地进行各种网络操作。

常用的Handler对象有:
1、HTTPHandler: 普通的HTPP处理器
2、HTTPSHandler:HTTPS处理器
3、ProxyHandler:代理IP处理器
4、HTTPCookieProcessor:cookie处理器

还有一些其他常见Handler对象:
【Python从入门到进阶】27、Handler处理器使用及代理和Cookie登录实现_第2张图片

Handler处理器的创建和调用步骤如下:
【Python从入门到进阶】27、Handler处理器使用及代理和Cookie登录实现_第3张图片

四、Handler处理器示例(包含代理和Cookie登录)

1、HTTPHandler处理器示例

import urllib.request

# 创建HTTPHandler处理器对象
handler = urllib.request.HTTPHandler()

# 创建OpenerDirector对象,并将HTTPHandler处理器添加进去
opener = urllib.request.build_opener(handler)

# 使用OpenerDirector对象发送HTTP请求
response = opener.open('http://www.baidu.com')

# 打印响应内容
print(response.read())

2、HTTPSHandler处理器示例

import urllib.request

# 创建HTTPSHandler处理器对象
handler = urllib.request.HTTPSHandler()

# 创建OpenerDirector对象,并将HTTPSHandler处理器添加进去
opener = urllib.request.build_opener(handler)

# 使用OpenerDirector对象发送HTTPS请求
response = opener.open('https://www.baidu.com')

# 打印响应内容
print(response.read())

3、ProxyHandler处理器示例

很多网站会检测某一段时间某个IP的访问次数(通过流量统计,系统日志等),如果访问字数多的不像正常人,它会禁止这个IP的访问。
所以我们可以设置一些代理服务器,每隔一段时间换一个代理,就算IP被禁止,依然可以换个IP继续爬取,从而突破自身IP访问限制,提高访问速度,同时隐藏真实IP。
我们可以在网上收集一些免费代理,测试可用后,将其收集起来用在爬虫上面。免费短期代理网站举例:
【快代理免费代理】https://www.kuaidaili.com/:
【Python从入门到进阶】27、Handler处理器使用及代理和Cookie登录实现_第4张图片
urllib2中通过ProxyHandler来设置使用代理服务器,下面代码说明如何使用自定义opener来使用代理:

(1)单一代理
import urllib.request

# 定义代理服务器地址和端口号
proxies = {
    'http': '114.231.82.176:8888'
}

# 创建ProxyHandler处理器对象,指定代理服务器
proxy_handler = urllib.request.ProxyHandler(proxies=proxies)

# 创建OpenerDirector对象,并将ProxyHandler处理器添加进去
opener = urllib.request.build_opener(proxy_handler)

# 使用OpenerDirector对象发送HTTP请求(通过代理)
response = opener.open('http://www.baidu.com')

# 打印响应内容
print(response.read())

在上述示例中,我们首先定义了代理服务器的地址和端口号,然后创建了ProxyHandler处理器对象,并通过参数传入代理服务器的地址和端口号。接下来,我们使用build_opener()函数创建OpenerDirector对象,并将ProxyHandler处理器添加进去。

当我们使用OpenerDirector对象发送HTTP请求时,请求将通过指定的代理服务器进行转发。这对于需要经过代理才能访问目标网站的场景非常有用。

(2)代理池代理

使用代理池可以实现每次请求从代理池中随机选择代理IP,避免重复使用同一IP被封。

import urllib.request
import urllib.error
import random

url = 'http://www.baidu.com/s?wd=ip'

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
                  "Chrome/98.0.4758.102 Safari/537.36 "
}

proxies_pool = [
    {'http': '114.231.82.176:8888'},
    {'http': '60.167.20.255:1133'},
    {'http': '222.74.73.202:42055'}
]

request = urllib.request.Request(url=url, headers=headers)

# 从proxies_pool中随机选择一个代理IP地址
proxies = random.choice(proxies_pool)

# (1) 创建ProxyHandler对象
handler = urllib.request.ProxyHandler(proxies=proxies)
# (2) 获取opener对象
opener = urllib.request.build_opener(handler)
# (3) 调用open方法
response = opener.open(request)

content = response.read().decode('utf-8')

with open('daili.html', 'w', encoding='utf-8') as f:
    f.write(content)

4、Cookie登录

(1)HTTPCookieProcessor的作用和使用场景

在网络爬虫和数据采集任务中,经常需要处理需要认证或账户授权的网站。使用HTTPCookieProcessor可以方便地处理和发送cookie,可以模拟用户登录并保持会话状态。通过在初始登录请求中接收和存储服务器返回的cookie,后续的请求将自动携带合适的cookie,以确保请求和响应之间的一致性,并获取所需的数据,使得在不同请求之间维持会话成为可能。

HTTPCookieProcessor是urllib库中的一个处理器对象,用于管理和处理HTTP请求和响应中的cookie信息。它可以自动处理来自服务器的Set-Cookie头部,并在后续的请求中自动发送相应的Cookie头部。

为了大家方便理解Cookie登录的细节,我们还要对Cookie的原理进行了解。

(2)cookie

Cookie是指某些网站服务器为了辨别用户身份和进行Session跟踪,而储存在用户浏览器上的文本文件,Cookie可以保持登录信息到用户下次与服务器的会话。

(3)Cookie原理

HTTP是无状态的面向连接的协议,为了保持连接状态,引入了Cookie机制,Cookie是HTTP消息头中的一种属性,包括:

Cookie名字(Name)
Cookie的值(Value)
Cookie的过期时间(Expires/Max-Age)
Cookie作用路径(Path)
Cookie所在域名(Domain),

使用Cookie进行安全连接(Secure)。

前两个参数是Cookie应用的必要条件,另外,还包括Cookie大小(Size,不同浏览器对Cookie个数及大小限制是有差异的)。
Cookie由变量名和值组成,根据Netscape公司的规定,Cookie格式如下:

Set-Cookie: NAME=VALUE;Expires=DATE;Path=PATH;Domain=DOMAIN_NAME;SECURE
(4)http.cookjar库

在Python3.x处理Cookie,一般是通过http.cookjar模块和urllib.request模块的HTTPCookieProcessor处理器类一起使用。

http.cookjar模块:主要作用是提供用于存储cookie的对象
HTTPCookieProcessor处理器:主要作用是处理这些cookie对象,并构建handler对象。

http.cookjar模块主要的对象有CookieJar、FileCookieJar、MozillaCookieJar、LWPCookieJar

●CookieJar:管理HTTP cookie值、存储HTTP请求生成的cookie、向传出的HTTP请求添加cookie的对象。整个cookie都存储在内存中,对CookieJar实例进行垃圾回收后cookie也将丢失。
●FileCookieJar(filename, delayload = None, policy = None):从CookieJar派生而来,用来创建FileCookieJar实例,检索cookie信息并将cookie存储到文件中。filename是存储cookie的文件名。delayload为True时支持延迟访问访问文件,即只有在需要时才读取文件或文件中存储数据。
●MozillaCookieJar(filename, delayload = None, policy = None):从FileCookieJar派生而来,创建与Mozilla浏览器cookies.txt兼容的FileCookieJar实例。
●LWPCookieJar(filename, delayload = None, policy = None):从FileCookieJar派生而来,创建与libwww-perl标准的Set-Cookie3文件格式兼容的FileCookieJar实例。

其实大多数情况下,我们只用CookieJar(),如果需要和本地文件交互,就用MozillaCookiejar()或LWPCookieJar()

(5)cookie登录案例
import urllib.request
import http.cookiejar
'''
目前某知和某瓣的反爬虫机制做的比较好,以我目前水平用urllib库暂时实现不了模拟登录= =
等后面学习到selenium库的时候,再进行实现,这里以www.test.com为例子;
这个例子没有遇到图形验证码,一般都要解析图形验证码的。
'''

# 构建一个CookieJar对象实例来保存cookie
cookie = http.cookiejar.CookieJar()
# 使用HTTPCookieProcessor()来创建cookie处理器对象,参数为CookieJar()对象
cookie_handler = urllib.request.HTTPCookieProcessor(cookie)
# 通过build_opener()来构建opener
opener = urllib.request.build_opener(cookie_handler)
# 设置User-Agent头:addheaders接受一个列表,里面每个元素都是一个headers信息的元组,opener将附带headers信息
opener.addheaders = [('User-Agent',
                      'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                      'Chrome/114.0.0.0 Safari/537.36'), ("Content-Type", "application/json;charset=UTF-8"),
                     ("Referer", "https://www.test.com/")]
# 需要登录的账户和密码
user = input("请输入您的账户:")
password = input("请输入您的密码:")
data = {
    'phone_num': user,
    'password': password
}
# 通过urlencode()转码
postdata = urllib.parse.urlencode(data)
postdata = postdata.encode(encoding="utf-8")  # str转bytes
# 构建Request请求对象,包含需要发送的用户名和密码
request = urllib.request.Request("https://www.test.com/login", data=postdata)
# 通过opener发送这个请求,并获取登录后的Cookie值
login_response = opener.open(request)
# 打印看看是不是反馈登录成功
print(login_response.read())
# opener包含用户登录后的Cookie值,可以直接访问那些登录后才可以访问的页面
response = opener.open("https://www.test.com/exampleInfo")
# 获取页面内容
html = response.read()
# 将页面内容存储至本地磁盘
fo = open("test.html", "wb")
fo.write(html)
fo.close()

模拟登录要注意几点:
●登录一般都会先有一个HTTP GET,用于获取一些信息及获得Cookie,然后再HTTP POST登录。
●HTTP POST登录的链接有可能是动态的,从GET返回的信息中获取。
●password(密码)有些是明文发送,有些是加密后发送。有些网站甚至采用动态加密的,同时包括了很多其他数据的加密信息,只能通过查看JS源码获得加密算法,再去破解加密,非常困难。
●大多数网站的登录整体流程是类似的,可能部分细节不一样,所以其他网站登录时,需根据具体情况,作对应的修改。

上述几个示例演示了如何使用不同类型的Handler处理器来处理HTTP请求、HTTPS请求、代理访问和Cookie登录。你可以根据具体需求和场景,选择适合的处理器并进行相应的配置。此外,你也可以自定义处理器,通过继承BaseHandler类来实现特定功能的处理器。

5、自定义处理器

下面是一个自定义处理器的示例,通过继承BaseHandler类来实现特定功能的处理器:

import urllib.request
from urllib.request import BaseHandler

# 自定义处理器继承BaseHandler类
class CustomHandler(BaseHandler):
    def __init__(self, custom_param):
        self.custom_param = custom_param

    def http_request(self, request):
        # 在发送HTTP请求前对请求进行修改
        print("CustomHandler: Modifying HTTP request with custom parameter:", self.custom_param)
        request.add_header('X-Custom-Param', self.custom_param)
        return request

    def http_response(self, request, response):
        # 在接收到HTTP响应后对响应进行解析或修改
        print("CustomHandler: Modifying HTTP response")
        # 打印响应头部信息
        print(response.info())
        return response

# 创建OpenerDirector对象,并将自定义处理器添加进去
opener = urllib.request.build_opener(CustomHandler("custom_value"))

# 使用OpenerDirector对象发送HTTP请求
response = opener.open('http://www.baidu.com')

# 打印响应内容
print(response.read())

在上述示例中,我们自定义了一个名为CustomHandler的处理器,它继承自BaseHandler类。该处理器在发送HTTP请求前,会添加一个自定义的参数(X-Custom-Param)到请求头中。而在接收到HTTP响应后,会打印响应的头部信息。

通过创建OpenerDirector对象并将自定义处理器添加进去,可以使得该处理器生效,并在发送HTTP请求时执行自定义的操作。

这个示例展示了如何使用继承BaseHandler类来编写自定义处理器,以实现特定功能或进行自定义修改。你可以根据具体需求,重写http_request()和http_response()等方法,并在这些方法中添加适当的逻辑来完成自定义的处理操作。


五、Handler处理器栈示例

我们之前的示例都是创建了一个处理器,实际上,我们可以一次性定义多个处理器来处理我们的网络请求。
不同的处理器可以按照一定的顺序组合在一起,形成处理器栈。当发送请求时,urllib库将按照处理器栈的顺序逐个调用每个处理器的方法,直到找到合适的处理器来处理请求。处理器之间的关系是层级式的,上层的处理器可以选择是否调用下层的处理器。
以下是一个示例:

import urllib.request
from urllib.request import HTTPHandler, HTTPSHandler

# 创建HTTPHandler和HTTPSHandler处理器对象
http_handler = HTTPHandler()
https_handler = HTTPSHandler()

# 创建OpenerDirector对象,并将处理器添加进去(按照顺序)
opener = urllib.request.build_opener(http_handler, https_handler)

# 使用OpenerDirector对象发送HTTP请求
response = opener.open('http://www.baidu.com')

# 打印响应内容
print(response.read())

在上述示例中,我们创建了HTTPHandler和HTTPSHandler两个处理器对象。然后,通过urllib.request.build_opener()函数将它们按照指定的顺序添加到OpenerDirector对象中,形成处理器栈。

当我们使用OpenerDirector对象发送HTTP请求时,它将按照处理器栈的顺序逐个调用每个处理器的相关方法,在适当的时候执行对应的操作。这样,我们可以灵活地组合不同类型的处理器来满足特定的需求,并确保请求被正确处理。

请注意,处理器的顺序很重要,因为它们会按照添加的顺序依次进行调用。如果有多个处理器能够处理同一类型的请求,那么位于处理器栈顶部的处理器将优先处理该请求。

如果没有特定类型的处理器匹配请求,那么默认的处理器会被调用。默认的处理器将根据URL的协议选择适当的处理器,并使用它来处理请求。

处理器可以根据需要进行灵活的配置和组合。你可以根据具体的需求自定义处理器栈,以满足不同的请求处理场景。对于复杂的应用程序,能够理解和合理配置处理器之间的关系和调用顺序非常重要。

参考:尚硅谷Python爬虫教程小白零基础速通教学视频

转载请注明出处:https://blog.csdn.net/acmman/article/details/131539711

你可能感兴趣的:(python爬虫,urllib,ProxyHandler,CookieProcessor,python代理)