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 urlopen 使用小示例
Sep 06 Python
Python struct模块解析
Jun 12 Python
Python获取某一天是星期几的方法示例
Jan 17 Python
Python输出由1,2,3,4组成的互不相同且无重复的三位数
Feb 01 Python
python实现类之间的方法互相调用
Apr 29 Python
python matplotlib绘图,修改坐标轴刻度为文字的实例
May 25 Python
Python多进程池 multiprocessing Pool用法示例
Sep 07 Python
python实现图片筛选程序
Oct 24 Python
python pands实现execl转csv 并修改csv指定列的方法
Dec 12 Python
如何利用python给图片添加半透明水印
Sep 06 Python
TensorBoard 计算图的查看方式
Feb 15 Python
记录模型训练时loss值的变化情况
Jun 16 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
php根据日期判断星座的函数分享
2014/02/13 PHP
PHP合并静态文件详解
2014/11/14 PHP
php+xml实现在线英文词典查询的方法
2015/01/23 PHP
php获取json数据所有的节点路径
2015/05/17 PHP
PHP中PDO的事务处理分析
2016/04/07 PHP
Laravel 实现密码重置功能
2018/02/23 PHP
php实现 master-worker 守护多进程模式的实例代码
2019/07/20 PHP
Javascript removeChild()删除节点及删除子节点的方法
2015/12/27 Javascript
深入理解JS函数的参数(arguments)的使用
2016/05/28 Javascript
轻松5句话解决JavaScript的作用域
2016/07/15 Javascript
JS数组去掉重复数据只保留一条的实现代码
2016/08/11 Javascript
ionic实现可滑动的tab选项卡切换效果
2020/04/15 Javascript
jQuery中的AjaxSubmit使用讲解
2016/09/25 Javascript
真正好用的js验证上传文件大小的简单方法
2016/10/27 Javascript
微信小程序页面开发注意事项整理
2017/05/18 Javascript
Javascript中 toFixed四舍六入方法
2017/08/21 Javascript
webpack项目调试以及独立打包配置文件的方法
2018/02/28 Javascript
Vue弹出菜单功能的实现代码
2018/09/12 Javascript
[03:49]辉夜杯现场龙骑士COSER秀情商“我喜欢芬队!”
2015/12/27 DOTA
一则python3的简单爬虫代码
2014/05/26 Python
举例讲解Python中metaclass元类的创建与使用
2016/06/30 Python
JSON Web Tokens的实现原理
2017/04/02 Python
python自动化测试之如何解析excel文件
2019/06/27 Python
Django中在xadmin中集成DjangoUeditor过程详解
2019/07/24 Python
pycharm配置当鼠标悬停时快速提示方法参数
2019/07/31 Python
初次部署django+gunicorn+nginx的方法步骤
2019/09/11 Python
python3实现弹弹球小游戏
2019/11/25 Python
python统计字符的个数代码实例
2020/02/07 Python
Python装饰器的应用场景代码总结
2020/04/10 Python
css3动画事件—webkitAnimationEnd与计时器time事件
2013/01/31 HTML / CSS
Expedia马来西亚旅游网站:廉价酒店,度假村和航班预订
2016/07/26 全球购物
Tory Burch美国官方网站:美国时尚生活品牌
2016/08/01 全球购物
南非最大的在线时尚商店:Zando
2019/07/21 全球购物
电子工程求职信
2014/07/17 职场文书
批评与自我批评范文
2014/10/15 职场文书
基于MySql验证的vsftpd虚拟用户
2021/11/07 MySQL