目录内容
urllib侧重于URL的请求构造
urllib2侧重于HTTP请求的处理
urllib3服务于升级的HTTP1.1标准,且拥有高效HTTP连接池管理以及HTTP代理服务的功能库
urllib3内容:
1、线程安全
2、连接池
3、客户端SSL/TLS验证
4、使用Multipart编码上传文件
5、协助处理重复请求和HTTP重定位
6、支持压缩编码
7、支持HTTP和SOCKS代理
8、100%测试覆盖率
4.1 sendrequest发送请求
- 引用urllib3模块,创建PoolManager类实例,管理连接池,可以通过request方法发送GET请求,
- request方法的返回值就是服务端的响应结果,可以通过data属性直接可以获得服务端的响应数据
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':'极客起源'})
# 获取百度服务端的返回值(byte形式),并使用UTF-8对其进行编码
data = response.data.decode('UTF-8')
# 输出百度服务端返回的内容
print(data)
4.2 sendpost发送HTTP POST请求
- 通过flask模块不安写一个可以处理HTTP POST请求的服务端程序,
# 支持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()
- 使用urllib3模块中相应的API向这个服务端程序发送HTTP POST请求,然后输出服务端的返回结果
from urllib3 import *
disable_warnings()
http = PoolManager()
# 指定要提交的HTTP POST请求的URL,/register是路由
url = 'http://localhost:5000/register'
# 想服务端发送HTTP PST请求,用fields关键字参数指定请求字段名和值
response = http.request('POST',url,fields={'name':'李青','age':18})
# 获取服务端返回数据
data = response.data.decode('utf-8')
# 输出服务端返回的数据
print(data)
- 运行结果
4.3 request_header请求头
通过request方法访问天猫商城的搜索功能,搜索功能的服务端必须依赖于HTTP请求头的cookie字段
- 第一步登录天猫获取cookie,按F12进入开发者模式
- 将cookie的内容保存到文本文档中,方便读取
- 通过读取cookie.txt的内容并加入到请求头中,编写代码如下
from urllib3 import *
import re
disable_warnings()
http = PoolManager()
# 定义天猫的搜索页面URL
url = 'https://list.tmall.com/search_product.htm?q=1&type=p&vmarket=&spm=875.7931836%2FB.a2227oh.d100&from=mallfp..pc_1_searchbutton'
# 从headers.txt文件读取HTTP请求头,并将其转换为字典形式
def str2Headers(file):
headerDict = {}
f = open(file,'r')
# 读取headers.txt文件中的所有内容
headersText = f.read()
headers = re.split('\n',headersText)
for header in headers:
result = re.split(':',header,maxsplit = 1)
headerDict[result[0]] = result[1]
f.close()
return headerDict
headers = str2Headers('headers.txt')
# 请求天猫的搜索页面,并传递HTTP请求头
response = http.request('GET',url,headers=headers)
# 将服务端返回的数据按GB18030格式解码
data = response.data.decode('GB18030')
print(data)
由上述代码可见,请求头是一种字典形式存放数据,cookie十分重要,不要随便泄漏。
4.4 headers_response响应头信息
使用HTTPResponse.info方法可以非常容易获取HTTP响应头的信息。其中HTTPResponse对象是request方法的返回值
# 获取百度的响应头消息
from urllib3 import *
disable_warnings()
http = PoolManager()
url = 'http://www.baidu.com'
response = http.request('GET',url)
# 输出所有响应头字段和值
for key in response.info().keys():
print(key,':',response.info()[key])
4.5 upload上传文件到服务器
# http是PoolManager类的实例
# 上传任意类型的文件(未指定文件类型)
# http.request('POST',url,fields={'files':(filename,fileData)})
# 上传文本类型的文件
# http.request('POST',url,fields={'files':(filename,fileData,'text/plain')})
# 上传jpeg类型的文件
# http.request('POST',url,fields={'files':(filename,fileData,'image/jpeg')})
- 编写服务器端
ps = '''实现了将文件上传到服务端的程序,可以通过输入本地文件名来上传任何类型的文件'''
import os
from flask import Flask,request
# 定义服务端保存上传文件的位置
UPLOAD_FOLDER = 'uploads'
app = Flask(__name__)
# 用于接收上传文件的路由需要使用POST方法
@app.route('/',methods=['POST'])
def upload_file():
# 获取上传文件的内容
file = request.files['files']
if file:
# 将上传的文件保存到upload子目录中
file.save(os.path.join(UPLOAD_FOLDER, os.path.basename(file.filename)))
return "文件上传成功"
if __name__ == '__main__':
app.run()
- 编写上传文件代码
from urllib3 import *
disable_warnings()
http = PoolManager()
# 定义上传文件的服务端URL
url = 'http://localhost:5000'
while True:
# 输入上传文件的名字
filename = input('请输入要上传的文件名字(必须在当前目录下):')
# 如果什么也没有输入,退出循环
if not filename:
break
# 用二进制的方式打开要上传的文件名,然后读取文件的所有内容,使用with语句会自动关闭打开的文件
with open(filename,'rb') as fp:
fileData = fp.read()
# 上传文件
response = http.request('POST',url,fields={'files':(filename,fileData)})
# 输出服务端的返回结果,本例是“文件上传成功”
print(response.data.decode('utf-8'))
- 注意:此处输入同一目录下的文件名直接上传,文件结构如下:
4.6 Timeout 超时
from urllib3 import *
disable_warnings()
# 通过PoolManager类的构造方法指定默认的连接超时和读超时
http = PoolManager(timeout=Timeout(connect=2.0,read=2.0))
url1 = 'https://www.baidu1122.com'
url2 = 'http://httpbin.org/delay/3'
try:
# 此处代码需要放在try…except中,否则一旦抛出异常,后面的代码将无法执行
# 下面的代码会抛出异常,因为域名www.baidu1122.com并不存在
# 由于连接超时设为2秒,
http.request('GET', url1,timeout=Timeout(connect=2.0,read=4.0))
except Exception as e:
print(e)
print('------------')
# 由于读超时为4秒,而url2指定的Url在3秒后就返回数据,所以不会抛出异常,
# 会正常输出服务器的返回结果
response = http.request('GET', url2,timeout=Timeout(connect=2.0,read=4.0))
print(response.info())
print('------------')
print(response.info()['Content-Length'])
# 由于读超时为2秒,所以会在2秒后抛出读超时异常
http.request('GET', url2,timeout=Timeout(connect=2.0,read=2.0))