Python爬虫-请求模块urllib3

Python爬虫-请求模块urllib3

urllib3是一个功能强大、条理清晰,用于HTTP 客户端的第三方模块,许多Python 的原生系统已经开始使用 urllib3。urllib3 提供了很多 Python 标准库里所没有的重要特性:
线程安全。
连接池。
客户端SSL/TLS验证。
使用 multipart编码上传文件。
Helpers用于重试请求并处理HTTP重定向。
支持gzip 和 deflate编码。
支持HTTP 和SOCKS 代理。
100%的测试覆盖率。
使用 urllib3 模块发送网络请求时,首先需要创建PoolManager对象,通过该对象调用request()方法来实现网络请求的发送。request()方法的语法格式如下:

request (method, url, fields = None, headers = None, urlopen_kw )

method:必选参数,用于指定请求方式,如GET、POST、PUT等。
url:必选参数,用于设置需要请求的URL地址。
fields:可选参数,用于设置请求参数。
headers:可选参数,用于设置请求头。
使用request()方法实现 GET请求

import urllib3    # 导入urllib3模块
url = "http://httpbin.org/get"
http = urllib3.PoolManager()   # 创建连接池管理对象
r = http.request('GET',url)    # 发送GET请求
print(r.status)                # 打印请求状态码

运行:

200

使用PoolManager对象向多个服务器发送请求
一个PoolManager对象就是一个连接池管理对象,通过该对象可以实现向多个服务器发送请求。示例代码如下:

import urllib3    # 导入urllib3模块
urllib3.disable_warnings()               # 关闭ssl警告
jingdong_url = 'https://www.jd.com/'     # 京东url地址
python_url = 'https://www.python.org/'   # Python url地址
baidu_url = 'https://www.baidu.com/'     # 百度url地址
http = urllib3.PoolManager()             # 创建连接池管理对象
r1 = http.request('GET',jingdong_url)    # 向京东地址发送GET请求
r2 = http.request('GET',python_url)      # 向python地址发送GET请求
r3 = http.request('GET',baidu_url)       # 向百度地址发送GET请求
print('京东请求状态码:',r1.status)
print('python请求状态码:',r2.status)
print('百度请求状态码:',r3.status)

运行:

京东请求状态码: 200
python请求状态码: 200
百度请求状态码: 200

使用request()方法实现POST请求
使用urllib3 模块向服务器发送 POST 请求时并不复杂,与发送GET 请求相似,只是需要在 request()
方法中将 method参数设置为“POST”,然后将 fields参数设置为字典类型的表单参数。示例代码如下:

import urllib3    # 导入urllib3模块
urllib3.disable_warnings()               # 关闭ssl警告
url = 'https://www.httpbin.org/post'    # post请求测试地址
params = {'name':'Jack','country':'中国','age':30}  # 定义字典类型的请求参数
http = urllib3.PoolManager()             # 创建连接池管理对象
r = http.request('POST',url,fields=params)    # 发送POST请求
print('返回结果:',r.data.decode('utf-8'))

运行:

返回结果: {
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "age": "30",
    "country": "\u4e2d\u56fd",
    "name": "Jack"
  },
  "headers": {
    "Accept-Encoding": "identity",
    "Content-Length": "307",
    "Content-Type": "multipart/form-data; boundary=c9ed20638057b1b745b6f4c875f7609d",
    "Host": "www.httpbin.org",
    "User-Agent": "python-urllib3/2.0.7",
    "X-Amzn-Trace-Id": "Root=1-66c039f0-2e8e92b95929522b717e3ec9"
  },
  "json": null,
  "origin": "61.136.223.36",
  "url": "https://www.httpbin.org/post"
}

通过retries参数设置重试请求
urllib3 模块可以自动重试请求,这种相同的机制还可以处理重定向。在默认情况下request()方法的请求重试次数为3次,如果需要修改重试次数可以设置 retries参数。修改重试测试的示例代码如下:

import urllib3    # 导入urllib3模块
urllib3.disable_warnings()               # 关闭ssl警告
url = 'https://www.httpbin.org/get'    # get请求测试地址
http = urllib3.PoolManager()             # 创建连接池管理对象
r = http.request('GET',url)              # 发送GET请求,默认重试请求
r1 = http.request('GET',url,retries=5)   # 发送GET请求,设置5次重试请求
r2 = http.request('GET',url,retries=False) # 发送GET请求,关闭重试请求
print('默认重试请求次数:',r.retries.total)
print('设置重试请求次数:',r1.retries.total)
print('关闭重试请求次数:',r2.retries.total)

运行:

默认重试请求次数: 3
设置重试请求次数: 5
关闭重试请求次数: False

通过info()方法获取响应头信息
发送网络请求后,将返回一个HTTPResponse对象,通过该对象中的info()方法即可获取HTTP响应头信息,该信息为字典(dict)类型的数据,所以需要通过for循环进行遍历才可清晰的看到每条响应头信息内容。示例代码如下:

import urllib3    # 导入urllib3模块
urllib3.disable_warnings()               # 关闭ssl警告
url = 'https://www.httpbin.org/get'    # get请求测试地址
http = urllib3.PoolManager()             # 创建连接池管理对象
r = http.request('GET',url)              # 发送GET请求,默认重试请求
response_header = r.info()               # 获取响应头
for key in response_header.keys():      # 循环遍历打印响应头信息
    print(key,':',response_header.get(key))

运行:

Date : Sat, 17 Aug 2024 05:54:28 GMT
Content-Type : application/json
Content-Length : 286
Connection : keep-alive
Server : gunicorn/19.9.0
Access-Control-Allow-Origin : *
Access-Control-Allow-Credentials : true

处理服务器返回的JSON信息
如果服务器返回了一条JSON信息,而这条信息中只有某条数据为可用数据时,可以先将返回的JSON数据转换为字典(dict)数据,接着直接获取指定键所对应的值即可。示例代码如下:

import urllib3    # 导入urllib3模块
import json       # 导入json模块
urllib3.disable_warnings()               # 关闭ssl警告
url = 'https://www.httpbin.org/post'    # post请求测试地址
params = {'name':'Jack','country':'中国','age':30}  # 定义字典类型的请求参数
http = urllib3.PoolManager()             # 创建连接池管理对象
r = http.request('POST',url,fields=params)    # 发送POST请求
j = json.loads(r.data.decode('unicode_escape'))  # 将响应数据转换为字典类型
print('数据类型:',type(j))
print('获取form对应的数据:',j.get('form'))
print('获取country对应的数据:',j.get('form').get('country'))

运行:

数据类型: <class 'dict'>
获取form对应的数据: {'age': '30', 'country': '中国', 'name': 'Jack'}
获取country对应的数据: 中国

处理服务器返回的二进制数据
如果响应数据为二进制数据,也可以做出相应的处理。例如,响应内容为图片的二进制数据时,则可以使用 open()函数,将二进制数据转换为图片。示例代码如下:

import urllib3    # 导入urllib3模块
urllib3.disable_warnings()               # 关闭ssl警告
url = 'https://img-blog.csdnimg.cn/img_convert/a2386b5dadeda8ffc771ba4c8c0c0b2f.png'  # 图片请求地址
http = urllib3.PoolManager()             # 创建连接池管理对象
r = http.request('GET',url)              # 发送网络请求
print(r.data)                            # 打印二进制数据
f = open('python.png','wb+')             # 创建open对象
f.write(r.data)                          # 写入数据
f.close()                                # 关闭

运行:

xb5e\xed\xdeE@\x17#c\x12s\x9e7\xc0\x03Fp\xa0\xb2X\xf0\xb1R\xc8=\x0e\xa8\xe2\x84\xb3J.\x16\x80u\xb8fv\x07Y\xec\x94l#v\x86\x8d\x00\xbd\xfd\xb3O\x91\xb7O;SU\x16\x17\x9b\xe9#=X\xebl\xff\xec\x13\xe4\xed5\xeb\xc8^\xbbJZGi~\x9e5\x1e\x8c\xc8\xb5\xc6\x86x\x17\x07WB\x99 \xd0\xb3cY\xae\x0c\xed\xca\x90\xb57\t)\x1f:\x80\x08T\xff\x8a\x13w\xa20=\x8d\x01!\xce~\xe8\xef\xf8j\xd5\nka\x8e\xda\x0c\x1d\xe6\xe8\xe2`\x04n\xb4\x00\tu\xa5\x02g\xb6*\x

在这里插入图片描述
复杂请求的发送
设置请求头
在这里插入图片描述
设置请求头信息
请求头信息获取完成以后,将“User-Agent”设置为字典(dict)数据中的键,后面的数据设置为字典(dict)中 value。示例代码如下:

import urllib3    # 导入urllib3模块
urllib3.disable_warnings()               # 关闭ssl警告
url = 'https://www.httpbin.org/get'    # get请求测试地址
# 定义火狐浏览器请求头信息
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:77.0) Gecko/20100101 Firefox/77.0'}
http = urllib3.PoolManager()                   # 创建连接池管理对象
r = http.request('GET',url,headers=headers)    # 发送GET请求
print(r.data.decode('utf-8'))                  # 打印返回内容

运行:

{
  "args": {},
  "headers": {
    "Accept-Encoding": "identity",
    "Host": "www.httpbin.org",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:77.0) Gecko/20100101 Firefox/77.0",
    "X-Amzn-Trace-Id": "Root=1-66c03daa-35b3202d795b1efd273ffb61"
  },
  "origin": "61.136.223.36",
  "url": "https://www.httpbin.org/get"
}

设置超时
在没有特殊要求的情况下,可以将设置超时的参数与时间填写在 request()方法或者是 PoolManager()实例对象中,示例代码如下:

import urllib3    # 导入urllib3模块
urllib3.disable_warnings()               # 关闭ssl警告
baidu_url = 'https://www.baidu.com/'    # 百度超时请求测试地址
python_url = 'https://www.python.org/'  # Python超时请求测试地址
http = urllib3.PoolManager()                   # 创建连接池管理对象
try:
    r = http.request('GET',baidu_url,timeout=0.01)# 发送GET请求,并设置超时时间为0.01秒
except  Exception as error:
    print('百度超时:',error)
http2 = urllib3.PoolManager(timeout=0.1)  # 创建连接池管理对象,并设置超时时间为0.1秒
try:
    r = http2.request('GET', python_url)  # 发送GET请求
except  Exception as error:
    print('Python超时:',error)

运行:

百度超时: HTTPSConnectionPool(host='www.baidu.com', port=443): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPSConnection object at 0x000002961EBF5BC8>, 'Connection to www.baidu.com timed out. (connect timeout=0.01)'))
Python超时: HTTPSConnectionPool(host='www.python.org', port=443): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPSConnection object at 0x000002961EC07308>, 'Connection to www.python.org timed out. (connect timeout=0.1)'))

上传文件
通过指定fields参数上传文本文件

import urllib3    # 导入urllib3模块
import json       # 导入json模块
with open('test.txt') as f:    # 打开文本文件
  data = f.read()               # 读取文件
http = urllib3.PoolManager()    # 创建连接池管理对象
# 发送网络请求
r = http.request( 'POST','http://httpbin.org/post',fields={'filefield': ('example.txt', data),})
files = json.loads(r.data.decode('utf-8'))['files']  # 获取上传文件内容
print(files)                                         # 打印上传文本信息

运行:

{'filefield': '在学习中寻找快乐!'}

通过指定body参数上传图片文件

import urllib3    # 导入urllib3模块
with open('python.jpg','rb') as f:  # 打开图片文件
  data = f.read()                    # 读取文件
http = urllib3.PoolManager()    # 创建连接池管理对象
# 发送请求
r = http.request('POST','http://httpbin.org/post',body = data,headers={'Content-Type':'image/jpeg'})
print(r.data.decode())          # 打印返回结果

运行:

{
  "args": {},
  "data": "data:application/octet-stream;base64,iVBORw0KGgoAAAANSUhEUgAAALEAAABACAYAAABV55Z5AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAABkjSURBVHhe7V0JnBTF9f7m

在这里插入图片描述

  • 18
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值