介绍
介绍
福哥今天要给大家分享一个基于urllib3的http客户端请求对象,大家都知道urllib库是Python用来模拟HTTP请求的,通过urllib库可以使用HTTP协议的GET/POST/PUT/DELETE等等请求。
模拟POST请求时候,可以传入POST数据,支持表单提交方式(application/x-www-form-urlencoded)和JSON方式(application/json)两种数据类型。
可以自定义HTTP头信息,最常用的就是修改浏览器信息(User-Agent)来达到欺骗服务器的目的。比如:我们设置了浏览器信息是一个iPhone端的Safari浏览器,服务器就会返回一个手机端的页面给我们。
可以自定义Cookie信息,绝大部分的网站的登录信息都是通过Cookie实现的,如果我们可以拿到有效的Cookie信息就可以欺骗服务器,让服务器将授权资源内容返回给我们。
TFHttpClient
介绍
urllib3是最新版本库,它有着非常强大的功能支持,还有着非常友好的对象结构设计,最主要的是无论是Python2.7还是Python3都可以使用它,所以福哥选择了urllib3做为依赖库。
福哥设计的这个TFHttpClient是一个仿照Java的Spring框架的WebClient对象的设计风格,就是在调用的时候每一步都是方法调用另一个方法这样的形式,这种设计现在非常主流,看看福哥是怎样实现的吧!
依赖
TFHttpClient依赖urllib、urllib3、json三个库,如果环境里没有的话可以通过pip直接安装。
pip install urllib pip install urllib3
属性
属性比较简单,福哥就在代码里通过注释给一一介绍一下吧
# http 句柄,用来调用urllib3的功能
http = urllib3.PoolManager()
# 请求方法
method = ""
# 请求URL地址
url = ""
# 请求QUERY_STRING
params = {}
# 表单提交数据
formData = None
# JSON数据
jsonData = None
# 自定义HTTP头信息
myHeaders = {}
# 自定义Cookie信息
myCookies = ""方法
get
启动一个GET方式的请求
def get(self, url, params=None): self.method = "get" self.url = url if params is not None: self.params = params return self
postForm
启动一个POST方式的请求,请求数据采用表单提交类型
def postForm(self, url, params=None, data=None): self.method = "post" self.url = url if params is not None: self.params = params if data is not None: self.formData = data return self
posJson
启动一个POST方式的请求,请求数据采用JSON类型
def postJson(self, url, params=None, data=None): self.method = "post" self.url = url if params is not None: self.params = params if data is not None: self.jsonData = data return self
cookies
设置Cookie信息,参数是一个对象类型
def cookies(self, cookies):
self.myCookies = urllib.urlencode(cookies, True)
self.myCookies = self.cookies.replace("&", "; ")
return selfheaders
设置HTTP信息,参数是一个对象类型
def headers(self, headers): self.myHeaders = headers return self
call
这是核心方法,负责组织请求信息,发送请求数据。如果请求失败会抛出异常,如果请求不是预期状态码也会抛出异常。
def call(self, charset="utf-8", wishStatus=200):
# prepare
if self.myCookies != "":
self.myHeaders["Cookie"] = self.myCookies
# request
res = None
if self.method == "get":
myUrl = self.url
myQuery = urllib.urlencode(self.params, True)
if myQuery != "":
if "?" not in myUrl:
myUrl += "?" + myQuery
else:
myUrl += "&" + myQuery
res = self.http.request(self.method, myUrl, headers=self.myHeaders)
elif self.method == "post":
myUrl = self.url
myQuery = urllib.urlencode(self.params, True)
if myQuery != "":
if "?" not in myUrl:
myUrl += "?" + myQuery
else:
myUrl += "&" + myQuery
myBody = ""
if self.formData is not None:
self.myHeaders['Content-Type'] = "application/x-www-form-urlencoded"
myBody = urllib.urlencode(self.formData, True)
elif self.jsonData is not None:
self.myHeaders['Content-Type'] = "application/json"
myBody = json.dumps(self.jsonData)
res = self.http.request(self.method, myUrl, body=myBody, headers=self.myHeaders)
# result
if res is not None:
if res.status == wishStatus:
return res
else:
raise Exception("Error: invalid status " + str(res.status))
else:
raise Exception("Error: no response")使用
代码
可以看到调用方法的过程没有一个赋值操作,全部都是方法调用,这种写法使代码结构很清晰。
因为Python的代码必须写一行上面,为了可以每一行写一个命令,需要在最外面放一个“()”把全部调用过程括起来。

总结
福哥今天带着童鞋们实现一个Python基于urllib3的http客户端请求对象——TFHttpClient,这个TFHttpClient的设计风格仿照的是Java的Spring框架的WebClient对象的,这种设计风格写出来的代码结构非常清晰,可读性非常好。