同福

Python基于urllib3的http客户端请求对象【20210118】

介绍

介绍

福哥今天要给大家分享一个基于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 self

headers

设置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的代码必须写一行上面,为了可以每一行写一个命令,需要在最外面放一个“()”把全部调用过程括起来。

2abbde6fbd02170a.jpg

总结

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