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中解析JSON并同时进行自定义编码处理实例
Feb 08 Python
利用aardio给python编写图形界面
Aug 21 Python
解决python 输出是省略号的问题
Apr 19 Python
Python小工具之消耗系统指定大小内存的方法
Dec 03 Python
对python requests发送json格式数据的实例详解
Dec 19 Python
python读取有密码的zip压缩文件实例
Feb 08 Python
Python 学习教程之networkx
Apr 15 Python
关于pandas的离散化,面元划分详解
Nov 22 Python
python 画3维轨迹图并进行比较的实例
Dec 06 Python
django 实现手动存储文件到model的FileField
Mar 30 Python
python导入库的具体方法
Jun 18 Python
解决pytorch 交叉熵损失输出为负数的问题
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
缓存技术详谈―php
2006/12/14 PHP
服务器web工具 php环境下
2010/12/29 PHP
分享常见的几种页面静态化的方法
2015/01/08 PHP
PHP实现使用DOM将XML数据存入数组的方法示例
2017/09/27 PHP
PHP针对redis常用操作实例详解
2019/08/17 PHP
javascript事件问题
2009/09/05 Javascript
使用Firebug对js进行断点调试的图文方法
2011/04/02 Javascript
web开发人员学习jQuery的6大理由及jQuery的优势介绍
2013/01/03 Javascript
简单的邮箱登陆的提示效果类似于yahoo邮箱
2014/02/26 Javascript
JQuery实现table行折叠效果以JSON做数据源
2014/05/26 Javascript
window.returnValue使用方法示例介绍
2014/07/03 Javascript
Javascript 绘制 sin 曲线过程附图
2014/08/21 Javascript
js计算任意值之间随机数的方法
2015/01/16 Javascript
实现点击下箭头变上箭头来回切换的两种方法【推荐】
2016/12/14 Javascript
JavaScript实现音乐自动切换和轮播
2017/11/05 Javascript
关于layui时间回显问题的解决方法
2019/09/24 Javascript
element-ui中按需引入的实现
2019/12/25 Javascript
使用Vue Composition API写出清晰、可扩展的表单实现
2020/06/10 Javascript
vue.js+element 默认提示中英文操作
2020/11/11 Javascript
Vue页面渲染中key的应用实例教程
2021/01/12 Vue.js
[01:05:40]VG vs Newbee 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/20 DOTA
Python文件与文件夹常见基本操作总结
2016/09/19 Python
python3+PyQt5实现自定义流体混合窗口部件
2018/04/24 Python
python使用time、datetime返回工作日列表实例代码
2019/05/09 Python
python通过函数名调用函数的几种场景
2020/09/23 Python
python实现简单的学生管理系统
2021/02/22 Python
CSS3的新特性介绍
2008/10/31 HTML / CSS
HEMA法国:荷兰原创设计
2019/02/21 全球购物
德国净水壶和滤芯品牌:波尔德PearlCo(家用净水器)
2020/04/29 全球购物
房屋买卖协议书
2014/04/10 职场文书
培训讲师岗位职责
2014/04/13 职场文书
《画风》教学反思
2014/04/16 职场文书
党员活动日总结
2014/05/05 职场文书
安全资料员岗位职责范本
2014/06/28 职场文书
高中运动会广播稿
2015/08/19 职场文书
公司管理建议书
2015/09/14 职场文书