python-request库

在对 httpapi 测试时,或者利用 api 实现批量添加、删除等等重复的工作时,必然需要利用一个发送 http 请求的库,今天介绍一个我在使用过程中感觉相当简单的一个库– requests

安装

python -m pip install requests

requests 支持 python 的版本为 2.7 以及 3.5+

模块说明

对于发送一个 http(s) 请求,无非就是

  • 发送一个请求
  • 对发送结果的处理,简单可以分为下面两部分
    • 发送成功后,对收到的数据处理
    • 发送失败,对异常状况的处理

首先需要明确一点, requests 是在 urllib3 这个很强大的,python 自带的库的基础上进行了重新封装,并提供给用户一套更简洁,使用更方便的接口

request 本身大概提供哪些接口呢?

from .models import Request, Response, PreparedRequest
from .api import request, get, head, post, patch, put, delete, options
from .sessions import session, Session
from .status_codes import codes
from .exceptions import (
    RequestException, Timeout, URLRequired,
    TooManyRedirects, HTTPError, ConnectionError,
    FileModeWarning, ConnectTimeout, ReadTimeout
)

上面这一部分主要涉及到几个可能会用到的类 Request, Response, PreparedRequest, Session

其他基本都是一些函数和异常的说明

所以重点回到上面提到的 4 个类

Session 负责和对方创建连接,Request 负责封装需要发送的信息, PreparedRequest 负责对 Request 封装的信息预处理,Response 主要是请求返回的信息

也就说, Session 中创建连接,发送( send ) Request, 得到 Response

这篇文章主要就是简单入门,不做太详细的介绍,之后有时间会完整的分析一下源码。

不要被上面 4 个类吓住了,在真正使用过程中,实际上特别简单

发送

如果看了上面的部分,会注意到

from .api import request, get, head, post, patch, put, delete, options

其实这几个函数就能实现我们发送的功能,首先解释一下几个接口

get, head, post, patch, put, delete, options 这些发送的类型实际上用的都是 request 接口, 无非就是调用 request 函数的时候,指定一下自己的 method

def get(url, params=None, **kwargs):
    kwargs.setdefault('allow_redirects', True)
    return request('get', url, params=params, **kwargs)

所以接口的重点就是 request

"""Constructs and sends a :class:`Request <Request>`.  

:param method: method for the new :class:`Request` object.

:param url: URL for the new :class:`Request` object.
    
:param params: (optional) Dictionary, list of tuples or bytes to send
        in the query string for the :class:`Request`.

:param data: (optional) Dictionary, list of tuples, bytes, or file-like
        object to send in the body of the :class:`Request`.
:param json: (optional) A JSON serializable Python object to send in the body of the :class:`Request`.
    
:param headers: (optional) Dictionary of HTTP Headers to send with the :class:`Request`.

:param cookies: (optional) Dict or CookieJar object to send with the :class:`Request`.

:param files: (optional) Dictionary of ``'name': file-like-objects`` (or ``{'name': file-tuple}``) for multipart encoding upload.
        ``file-tuple`` can be a 2-tuple ``('filename', fileobj)``, 3-tuple ``('filename', fileobj, 'content_type')``
        or a 4-tuple ``('filename', fileobj, 'content_type', custom_headers)``, where ``'content-type'`` is a string
        defining the content type of the given file and ``custom_headers`` a dict-like object containing additional headers
        to add for the file.

:param auth: (optional) Auth tuple to enable Basic/Digest/Custom HTTP Auth.

:param timeout: (optional) How many seconds to wait for the server to send data
        before giving up, as a float, or a :ref:`(connect timeout, read
        timeout) <timeouts>` tuple.
:type timeout: float or tuple

:param allow_redirects: (optional) Boolean. Enable/disable GET/OPTIONS/POST/PUT/PATCH/DELETE/HEAD redirection. Defaults to ``True``.
:type allow_redirects: bool

:param proxies: (optional) Dictionary mapping protocol to the URL of the proxy.

:param verify: (optional) Either a boolean, in which case it controls whether we verify
            the server's TLS certificate, or a string, in which case it must be a path
            to a CA bundle to use. Defaults to ``True``.

:param stream: (optional) if ``False``, the response content will be immediately downloaded.

:param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair.

:return: :class:`Response <Response>` object
:rtype: requests.Response

官方的文档里介绍的有点多,我挑几个日常可能使用频率比较高的

  • methon 中填写请求的类型, 例如 GET, POST, DELETE 等等,看 get() 等方法里,小写也可以
  • url 字段填写 http 的正常地址
  • 接下来是可扩充的额外字段
    • header 中放一些请求的头信息, 比如指明解析方式的 Content-Type:application/json, 连接方式Connection:keep-alive 等一般都是放在 header
    • Post 请求中Body体的内容用 data 或者 json
    • timeout 自定义请求超时时间

示例:

import requests
req = requests.request('GET', 'https://www.baidu.com')
print(req.status_code)

因为返回的是一个 Response 对象,具体可以从中获取哪些信息,可以直接跳转到 Response 的类中查看

回复的处理

一般通信之间都会使用 json 格式, 传输数据, 假设我们这里 url 可以得到一个 json 为例:

req = requests.request('GET', 'https://www.baidu.com')
if req.status_code == 200 :
    try:
        res_json = req.json()
    except ValueError:
        print("解析失败")

这里的 req.json(), 它实际上就是对返回的结果 req.text 做了一次 json.loads 的处理,所以最基本的做法是

req = requests.request('GET', 'https://www.baidu.com')
if req.status_code == 200 :
    print(req.text)

异常

前面介绍的时候提到异常

from .exceptions import (
    RequestException, Timeout, URLRequired,
    TooManyRedirects, HTTPError, ConnectionError,
    FileModeWarning, ConnectTimeout, ReadTimeout
)

注意一点,这里的超时也是一种异常,所以我们在发送请求时候的如果设置了 超时时间 是需要通过 try ... except 来捕获的

import requests 

try:
    req = requests.request('GET', 'https://github.com/',timeout=1)
except requests.exceptions.Timeout:
    print("请求超时")

总结

虽然我这里写的很简单,但是发送请求的参数实际上可以实现很多功能,文件的上传下载,设置代理,Cookies 等等,感兴趣的可以查阅一下官方的文档

https://requests.readthedocs.io/

requests 使用起来很方便,功能也很强大,是个值得学习的库~