urllib3 是一个基于python3的功能强大,友好的http客户端。越来越多的python应用开始采用urllib3.它提供了很多python标准库里没有的重要功能。
导入urllib3库
import urllib3
然后需要实例化一个PoolManager对象构造请求,这个对象处理了连接池和线程池的所有细节,所以我们不用自行处理。
http = urllib3.PoolManager()
用request()方法发送一个请求
r = http.request('GET', 'http://httpbin.org/robots.txt')
b'Uesr-agent:*\nDisallow: /deny\n'
可以用request()方法发送任意http请求,我们发一个post请求
r = http.request(
'POST',
'http://httpbin.org/post',
fields=('hello':'world')
)
http响应对象提供status,data和header等属性。
http = urllib3.PoolManager()
r = http.request('GET', 'http://httpbin.org/ip')
print(r.status)
print(r.data)
print(r.headers)
'''
运行结果
200
b'{\n "origin": "221.178.125.122"\n}\n'
HTTPHeaderDict({'Date': 'Tue, 25 Feb 2020 12:00:23 GMT', 'Content-Type': 'application/json', 'Content-Length': '34', 'Connection': 'keep-alive', 'Server': 'gunicorn/19.9.0', 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Credentials': 'true'})
'''
返回的json格式数据可以通过json模块,load为字典数据类型。
import urllib3
import json
http = urllib3.PoolManager()
r = http.request('GET', 'http://httpbin.org/ip')
print(json.loads(r.data.decode('utf-8')))
'''
运行结果
{'origin': '221.178.125.122'}
'''
响应返回的数据都是字节类型,对于大量的数据我们通过
stream来处理好:
http = urllib3.PoolManager()
r = http.request('GET', 'http://httpbin.org/bytes/1024',preload_content=False)
for chunk in r.stream(32):
print(chunk)
也可以当作一个文件对象来处理
http = urllib3.PoolManager()
r = http.request('GET', 'http://httpbin.org/bytes/1024',preload_content=False)
for line in r:
print(line)
可以利用ProxyManager进行http代理操作
proxy = urllib3.ProxyManager('http://180.76.111.69:3128')
res = proxy.request('get', 'http://httpbin.org/ip')
print(res.data)
request方法中添加字典格式的headers参数去指定请求头
http = urllib3.PoolManager()
r = http.request('GET', 'http;//httpbin.org/headers', headers={'key': 'value'})
print(json.loads(r,data,decode('utf-8')))
get,head,delete请求,可以通过提供字典类型的参数fields来添加查询参数。
http = urllib3.PoolManager()
r = http.request(
'GET',
'http://httpbin.org/get',
fields={'arg': 'value'}
)
print(json.loads(r.data.decode(utf-8))['args'])
对于post和put请求, 如果需要查询参数,需要通过url编码将参数编码正确个格式然后拼接到url中
import urllib3
import json
from urllib.parse import urlencode
http = urllib3.PoolManager()
encoded_args = urlencode({'args': 'value'})
url = 'http://httpbin.org/post?' + encode_args
r = http.request('POST', url)
print(json.loads(r.data.decode('utf-8'))['args'])
对于put和post请求,需要提供字典类型的参数field来传递form表单数据。
r = http.request('POST', 'http://httpbin/post',fields={'field: 'value'})
print(json.loads(r.data.decode('utf-8'))['form'])
当我们需要发送json数据时,我们需要在request中传入编码后的二进制数据类型的body参加数,并制定Content-type的请求头
http = urllib3.PoolManager()
data = {'attribute': 'value'}
encode_data = json.dumps(data).encode('utf-8')
r = http.request(
'post'
'http://httpbin.org/post',
body=encoded_data,
headers={'Content-Type': 'application/json'}
)
print(json.load(r.data.decode('utf-8'))['json'])
对于文件上传,我们可以模仿浏览器表单的方式
with open('example.text') as f:
file_data = f.read()
r = http.request(
'POST',
'http://httpbin.org/post',
fields={
'filefied':('example.txt', file_data),
})
print(json.loads(r.data.decode('utf-8'))['files'])
对于二进制数据的上传,我们用指定body的方式,并设置Content-Type的请求头
http = urllib3.PoolManger()
with open('example.jpg','rb') as f:
binary_data = f.read()
r = http.request(
'post',
'http://httpbin.org/post',
body=binary_data,
headers={'Content-Type':'image/jpeg'}
)
print(json.loads(r.data.decode('utf-8')))
a.找到目标数据
b.分析请求流程
c.构造http请求
d.提取清洗数据
e.数据持久化
import urllib3
import re
'''
下载百度首页所有图片
'''
# 1.寻找目标数据
page_url = 'https://image.baidu.com/search/index?tn=baiduimage&ct=201326592&lm=-1&cl=2&ie=gb18030&word=%CD%BC%C6%AC&fr=ala&ala=1&alatpl=adress&pos=0&hs=2&xthttps=111111'
# 2.分析请求流程
# 图片是浏览器下载下来的
# 图片的url,会比图片更早的下载回来
# 下载html
http = urllib3.PoolManager()
res = http.request('GET', page_url)
html = res.data.decode('utf-8') # 网页源码搜索charset,查看编码类型
# 提取url
img_urls = re.findall(r'"thumbURL":"(.*?)"', html)
# 加上headers伪装
header = {
"Referer": "https://image.baidu.com/search/index?tn=baiduimage&ct=201326592&lm=-1&cl=2&ie=gb18030&word=%CD%BC%C6%AC&fr=ala&ala=1&alatpl=adress&pos=0&hs=2&xthttps=111111"
}
# 遍历 下载
for index, img_url in enumerate(img_urls):
img_res = http.request('GET', img_url, headers=header)
# print(img_res.data)
# 动态拼接文件名
img_name = '%s.%s' % (index, img_url.split('.')[-1])
with open(img_name, 'wb') as f:
f.write(img_res.data)