Python Handler处理器和自定义Opener原理详解


Posted in Python onMarch 05, 2020

我们之前一直都在使用的urlopen,这是一个特殊的opener(也就是模块帮我们构建好的)。

但是基本的urlopen()方法不支持代理、cookie等其他的HTTP/HTTPS高级功能。所以要支持这些功能:

1.使用相差的Handler处理器来创建特定功能的处理器对象;

2.然后通过urllib.request.build_opener()方法,创建自定义opener对象

3.使用自定义的opener对象,调用open()方法发送请求。

如果程序里所有的请求都使用自定义的opener,可以使用urllib.request.install_opener()将自定义的opener对象定义为全局opener,表示如果之后凡是调用urlopen,都将使用这个opener(根据自己的需求来选择)

简单的自定义opener()

#!/usr/bin/python3
# -*- coding:utf-8 -*-
__author__ = 'mayi'
import urllib.request
# 构建一个HTTPHandler处理器对象,支持处理HTTP请求。
http_handler = urllib.request.HTTPHandler()
# # 构建一个HTTPSHandler处理器对象,支持处理HTTPS请求
# https_handler = urllib.request.HTTPSHandler()
# 调用urllib.request.build_opener()方法,创建支持处理HTTP请求的opener对象
opener = urllib.request.build_opener(http_handler)
# 构建Request请求
request = urllib.request.Request("http://www.baidu.com/")
# 调用自定义opener对象的open()方法,发送request请求
response = opener.open(request)
# 获取服务器响应内容
html = response.read()
print(html)

这种方式发送请求得到的结果,和使用urllib.request.urlopen()发送HTTP/HTTPS请求得到的结果是一样的。

如果在HTTPHandler()增加debuglevel = 1参数,还会将Debug Log打开,这样程序在执行的时候,会把收包和发包的报头在屏幕上自动打印出来,方便调度,有时可以省去抓包的工作。

# 仅需要修改的代码部分:
# 构建一个HTTPHandler 处理器对象,支持处理HTTP请求,同时开启Debug Log,debuglevel 值默认 0
http_handler = urllib.request.HTTPHandler(debuglevel = 1)
# 构建一个HTTPHSandler 处理器对象,支持处理HTTPS请求,同时开启Debug Log,debuglevel 值默认 0
https_handler = urllib.request.HTTPSHandler(debuglevel = 1)

ProxyHandler处理器(IP代理设置)

很多网站会检测某一段时间IP的访问次数(通过流量统计、系统日志等),如果某个IP访问次数多的不像正常人,它会禁止这个IP的访问。

所以我们通常可以设置一些代理服务器,每隔一段时间换一个代理,就算IP被禁止,依然可以换个IP继续爬取。

urllib.request中通过ProxyHandler来设置使用代理服务器,下面代码说明如何使用自定义opener来使用代理:

#!/usr/bin/python3
# -*- coding:utf-8 -*-
__author__ = 'mayi'
 
"""
ProxyHandler处理器(代理设置)
很多网站会检测某一段时间某个IP的访问次数(通过流量统计,系统日志等),如果
访问次数多的不像正常人,它会禁止这个IP的访问。
所以我们可能通过设置一些代理服务器,每隔一段时间换一个代理IP,就算IP被禁
止,我们依然可以换个IP继续爬取。
"""
 
import urllib.request
 
# 构建了两个代理Handler,一个有代理IP,一个没有代理IP
http_proxy_handler = urllib.request.ProxyHandler({"http":"222.33.192.238:8118"})
null_proxy_handler = urllib.request.ProxyHandler({})
 
# 定义一个代理开关
proxy_switch = True
 
# 根据代理开关是否拱形,使用不同的代理模式
# 通过urllib.request.build_opener()方法使用这些代理Handler对象,创建自定义opener对象
if proxy_switch:
  opener = urllib.request.build_opener(http_proxy_handler)
else:
  opener = urllib.request.build_opener(null_proxy_handler)
 
request = urllib.request.Request("http://www.baidu.com/")
# 1. 如果这么写,只有使用opener.open()方法发送请求才使用自定义的代理,而urlopen()则不使用自定义代理。
response = opener.open(request)
# 2. 如果这么写,就是将opener应用到全局,之后所有的,不管是opener.open()还是urlopen() 发送请求,都将使用自定义代理。
# urllib.request.install_opener(opener)
# response = urlopen(request)
html = response.read()
 
print(html)

免费的开放代理获取基本没有什么成本,我们可以在一些代理网站上收集这些免费代理,测试后如果可以用,就把它收集起来用在爬虫上面。

免费代理网站举例:

  • 西刺免费代理IP

  • 快代理免费代理

  • Proxy360代理

  • 全网代理IP

如果代理IP足够多,就可以让程序随机获取一个代理IP去访问网站。

import random
proxy_list = [
  {"http" : "1.85.220.77:8118"},
  {"http" : "110.73.6.57:8123"},
  {"http" : "171.39.4.8:8123"},
  {"http" : "122.244.53.133:808"},
  {"http" : "171.39.75.81:8123"}
]
# 随机选择一个代理
proxy = random.choice(proxy_list)

但是,这些免费开放的代理一般会有很多人都在使用,而且代理有寿命短、速度慢、匿名度不高、HTTP/HTTPS支持不稳定等缺点。

所以,要根据自己的需求,选择是否需要使用高品质的私密代理(通常需要找专门的代理供应商购买,再通过用户名/密码授权使用)。

Cookie

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

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

http.cookiejar库和HTTPCookieProcessor处理器

在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()

案例:利用http.cookiejar和post登录人人网

#!/usr/bin/python3
# -*- coding:utf-8 -*-
__author__ = 'mayi'
 
"""
利用http.cookiejar和post登录人人网
url = "http://www.renren.com/PLogin.do"
"""
 
import urllib
import urllib.request
import http.cookiejar
 
# 构建一个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 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36')]
# 需要登录的账户和密码
email = input("请输入您的账户:")
password = input("请输入您的密码:")
data = {"email": email, "password": password}
# 通过urlencode()转码
postdata = urllib.parse.urlencode(data)
postdata = postdata.encode(encoding = "utf-8") # str转bytes
# 构建Request请求对象,包含需要发送的用户名和密码
request = urllib.request.Request("http://www.renren.com/PLogin.do", data = postdata)
# 通过opener发送这个请求,并获取登录后的Cookie值
opener.open(request)
# opener包含用户登录后的Cookie值,可以直接访问那些登录后才可以访问的页面
response = opener.open("http://www.renren.com/413928886/profile")
# 获取页面内容
html = response.read()
# 将页面内容存储至本地磁盘
fo = open("renren.html", "wb")
fo.write(html)
fo.close()

模拟登录要注意几点:

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python开发常用的一些开源Package分享
Feb 14 Python
Python中使用gzip模块压缩文件的简单教程
Apr 08 Python
python中字符串前面加r的作用
Jun 04 Python
python用reduce和map把字符串转为数字的方法
Dec 19 Python
Python实现Windows和Linux之间互相传输文件(文件夹)的方法
May 08 Python
在PyCharm的 Terminal(终端)切换Python版本的方法
Aug 02 Python
python打印异常信息的两种实现方式
Dec 24 Python
python程序文件扩展名知识点详解
Feb 27 Python
python爬虫快速响应服务器的做法
Nov 24 Python
详解BeautifulSoup获取特定标签下内容的方法
Dec 07 Python
python3操作redis实现List列表实例
Aug 04 Python
Python通用验证码识别OCR库ddddocr的安装使用教程
Jul 07 Python
Python使用进程Process模块管理资源
Mar 05 #Python
Python json模块与jsonpath模块区别详解
Mar 05 #Python
Python如何用filter函数筛选数据
Mar 05 #Python
Python API len函数操作过程解析
Mar 05 #Python
Python通过Tesseract库实现文字识别
Mar 05 #Python
Python爬虫实现模拟点击动态页面
Mar 05 #Python
python实现图片横向和纵向拼接
Mar 05 #Python
You might like
百事可乐也出咖啡了 双倍咖啡因双倍快乐
2021/03/03 咖啡文化
教你如何把一篇文章按要求分段
2006/10/09 PHP
PHP 文件类型判断代码
2009/03/13 PHP
简单谈谈php浮点数精确运算
2016/03/10 PHP
php结合web uploader插件实现分片上传文件
2016/05/10 PHP
PHP implode()函数用法讲解
2019/03/08 PHP
Windows服务器中PHP如何安装redis扩展
2019/09/27 PHP
Laravel框架控制器,视图及模型操作图文详解
2019/12/04 PHP
js每次Title显示不同的名言
2008/09/25 Javascript
jquery右下角弹出提示框示例代码
2013/10/08 Javascript
javascript内置对象arguments详解
2014/03/16 Javascript
谷歌浏览器不支持showModalDialog模态对话框的解决方法
2014/09/22 Javascript
基于Jquery easyui 选中特定的tab
2015/11/17 Javascript
jQuery实现图像旋转动画效果
2016/05/29 Javascript
浅析Javascript中bind()方法的使用与实现
2016/05/30 Javascript
解决layui数据表格Date日期格式的回显Object的问题
2019/09/19 Javascript
VUE子组件向父组件传值详解(含传多值及添加额外参数场景)
2020/09/01 Javascript
解决vue scoped html样式无效的问题
2020/10/24 Javascript
JavaScript 如何在浏览器中使用摄像头
2020/12/02 Javascript
Python Web框架Flask中使用七牛云存储实例
2015/02/08 Python
python使用装饰器和线程限制函数执行时间的方法
2015/04/18 Python
Ubuntu下Python+Flask分分钟搭建自己的服务器教程
2019/11/19 Python
在python中使用nohup命令说明
2020/04/16 Python
Python venv虚拟环境配置过程解析
2020/07/08 Python
波兰运动鞋网上商店:e-Sporting
2018/02/16 全球购物
微软台湾官方网站:Microsoft台湾
2018/08/15 全球购物
系统管理员的职责包括那些?管理的对象是什么?
2013/01/18 面试题
软件配置管理有什么好处
2015/04/15 面试题
实习期自我鉴定
2013/10/11 职场文书
《冬阳童年骆驼队》教学反思
2014/04/15 职场文书
夫妻分居协议书范本
2014/11/28 职场文书
幼儿园老师新年寄语2015
2014/12/08 职场文书
解决Golang time.Parse和time.Format的时区问题
2021/04/29 Golang
HTML5来实现本地文件读取和写入的实现方法
2021/05/25 HTML / CSS
python数字图像处理之图像自动阈值分割示例
2022/06/28 Python
zabbix如何添加监控主机和自定义监控项
2022/08/14 Servers