【Python爬虫】哇!又来一个强大的Python网络库:Urllib3

2021-03-29 15:24:25 浏览数 (1)

在Python程序中,使用频率最高的网络模块莫过于urllib,由于urllib是Python内置的网络模块,不需要单独安装,使用起来非常方便。但随着互联网的不断发展,urllib里的功能明显已经不够用了,所以有了后来的urllib2和urllib3。

从前文的内容来看,urllib中的API大多与URL相关,所以可以得出这样一个结论,urllib主要侧重与URL的请求构造。 而urllib2侧重于HTTP请求的处理, urllib3则是服务于升级的HTTP 1.1标准,且拥有高效 HTTP连接池管理及HTTP 代理服务的功能库,从 urllib 到 urllib2和 urllib3是顺应互联应用升级浪潮的,这股浪潮从通用的网络连接服务到互联网网络的头部应用,支持长连接的 HTTP访问,网络访问不断的便捷化。

1. urllib3模块

urllib3是一个功能强大,条理清晰,用于编写HTTP客户端的Python库,许多Python的原生系统已经开始使用urllib3。urllib3提供了很多python标准库里所没有的重要特性,这些特性包括:

  • 线程安全
  • 连接池
  • 客户端SSL/TLS验证
  • 使用multipart编码上传文件
  • 协助处理重复请求和HTTP重定位
  • 支持压缩编码
  • 支持HTTP和SOCKS代理
  • 100%测试覆盖率

urllib3并不是Python语言的标准模块,因此,使用urllib3之前需要使用pip命令或conda命令安装urllib3。

代码语言:javascript复制
pip install urllib3

代码语言:javascript复制
conda install urllib3

2. 发送HTTP GET请求

使用urllib3中的API向服务端发送HTTP请求,首先需要引用urllib3模块,然后创建PoolManager类的实例,该类用于管理连接池。最后就可以通过request方法发送GET请求了,request方法的返回值就是服务端的响应结果,通过data属性直接可以获得服务端的响应数据。看看,是不是非常简单呢!

当向服务端发送HTTP GET请求时,而且请求字段值包含中文、空格等字符,需要对其进行编码。在urllib.parse模块中有一个urlencode函数,可以将一个字典形式的请求值对作为参数传入urlencode函数,该函数返回编码结果。

代码语言:javascript复制
# 使用urlencode函数将“极客起源“转换为URL编码形式print(urlencode({'wd':'极客起源'}))

执行上面的代码,会输出如下的内容。

代码语言:javascript复制
wd=极客起源

使用request方法发送HTTP GET请求时,可以使用urlencode函数对GET字段进行编码,也可以直接使用fields关键字参数指定字典形式的GET请求字段。使用这种方式,request方法会自动对fields关键字参数指定的GET请求字段进行编码。

代码语言:javascript复制
# http是PoolManager类的实例变量http.request('GET', url,fields={'wd':'极客起源'})

本例通过urllib3中的API向百度(http://www.baidu.com)发送查询请求,然后获取并输出百度的搜索结果。

代码语言:javascript复制
from urllib3 import *# urlencode函数在urllib.parse模块中from urllib.parse import urlencode# 调用disable_warnings函数可以阻止显示警告消息disable_warnings()# 创建PoolManager类的实例http = PoolManager()'''# 下面的代码通过组合URL的方式向百度发送请求url = 'http://www.baidu.com/s?'   urlencode({'wd':'极客起源'})print(url)response = http.request('GET', url)'''url = 'http://www.baidu.com/s'# 直接使用fields关键字参数指定GET请求字段response = http.request('GET', url,fields={'wd':'极客起源'})# 获取百度服务端的返回值(字节形式),并使用UTF-8格式对其进行解码data = response.data.decode('UTF-8')# 输出百度服务端返回的内容print(data)

运行结果如图1所示。由于百度服务端返回的内容很多,这里只显示了一部分返回内容。

3. 发送HTTP POST请求

如果要向服务端发送比较复杂的数据,通过HTTP GET请求就不太合适,因为HTTP GET请求将要发送的数据都放到了URL中。因此,当向服务端发送复杂数据时建议使用HTTP POST请求。

HTTP POST请求与HTTP GET请求的使用方法类似,只是在向服务端发送数据时,传递数据会跟在HTTP请求头后面,因此,可以使用HTTP POST请求发送任何类型的数据,包括二进制形式的文件(一般会将这样的文件使用Base64或其他编码格式进行编码)。为了能更好地理解HTTP POST请求,本节首先会使用Flask编写一个专门接收HTTP POST请求的服务端。

Flask属于Python语言的第三方模块,需要单独安装,不过如果读者使用的是Anaconda Python开发环境,就不需要安装flask模块了,因为Anaconda已将flask模块集成到里面了。如果读者使用的是标准的Python开发环境,可以使用pip install flask命令安装flask模块。本节只是利用了flask模块编写一个简单的可以处理HTTP POST请求的服务端程序。

本例通过flask模块编写一个可以处理HTTP POST请求的服务端程序,然后使用urllib3模块中相应的API向这个服务端程序发送HTTP POST请求,然后输出服务端的返回结果。

代码语言:javascript复制
# 支持HTTP POST请求的服务端程序from flask import Flask, request# 创建Flask对象,任何基于flask模块的服务端应用都必须创建Flask对象app = Flask(__name__)# 设置/register路由,该路由可以处理HTTP POST请求@app.route('/register', methods=['POST'])def register():    # 输出名为name的请求字字段的值print(request.form.get('name'))# 输出名为age的请求字段的值print(request.form.get('age'))# 向客户端返回“注册成功”消息    return '注册成功' if __name__ == '__main__':    # 开始运行服务端程序,默认端口号是5000    app.run()

在上面的程序中涉及到一个路由的概念,其实路由就是在浏览器地址栏中输入的一个Path(跟在域名或IP后面),flask模块会将路由对应的Path映射到服务端的一个函数,也就是说,如果在浏览器地址栏中输入特定的路由,flask模块的相应API接收到这个请求,就会自动调用该路由对应的函数。如果不指定methods,默认可以处理HTTP GET请求,如果要处理HTTP POST请求,需要设置methods的值为['POST']。Flask在处理HTTP POST的请求字段时,会将这些请求保存到字典中,form属性就是这个字典变量。

现在运行上面的程序,会发现程序在Console中输出一行如下的信息。

代码语言:javascript复制
* Running on http://127.0.0.1:5000/ (Press CTRL C to quit)

这表明使用flask模块建立的服务端程序的默认端口号是5000。

代码语言:javascript复制
from urllib3 import *disable_warnings()http = PoolManager()# 指定要提交HTTP POST请求的URL,/register是路由url = 'http://localhost:5000/register'# 向服务端发送HTTP POST请求,用fields关键字参数指定HTTP POST请求字段名和值response = http.request('POST', url,fields={'name':'李宁','age':18})# 获取服务端返回的数据data = response.data.decode('UTF-8')# 输出服务端返回的数据print(data)

在运行上面的程序之前,首先应运行server.py,程序会在Console中输出“注册成功”消息,而服务端的Console中会输出如图2所示的信息。

- EOF -

推荐阅读 点击标题可跳转

编写爬虫竟然成了“面向监狱编程”,就是因为不懂Robots协议(爬虫协议)

卧槽,好强大的魔法,竟能让Python支持方法重载

Python装饰器(decorator)不过如此,是我想多了

这样合并Python字典,可以让程序的运行效率提高4倍

Python代码可以加密吗?Python字节码告诉你!

使出Python的六脉神剑,让Python拥有无限扩展性

Python生成器(Generator)最完美解释

关注「极客起源」公众号,加星标,不错过精彩技术干货

0 人点赞