📜  urllib3 python (1)

📅  最后修改于: 2023-12-03 15:35:32.156000             🧑  作者: Mango

urllib3 Python库介绍

urllib3 是一个功能丰富,线程安全且具有文档的 HTTP 客户端库,适用于 Python 2.7 和 3.x。它具有以下特征:

  • 线程安全的连接池
  • 支持文件上传
  • 支持 HTTP(S) 代理
  • 支持自定义证书验证
  • 支持 Keep-Alive 连接
  • 自动支持 Content-Encoding ( gzip、deflate)
  • 支持重定向和消息的 Retry
  • 高度基于 HTTP 协议规范
  • 遵循 RFC3986 规范的 URL 解析和编码
  • 可通过高级功能扩展连接池
安装

使用 pip 安装 urllib3

pip install urllib3
使用

导入 urllib3 之后,您就可以创建 PoolManager 的实例,并使用它来发出 HTTP 请求。下面是一个简单的示例:

import urllib3

if __name__ == '__main__':
    http = urllib3.PoolManager()
    url = "https://www.baidu.com"
    response = http.request('GET', url)
    print(response.status)
    print(response.data.decode())

该示例向百度发送请求,并打印出响应状态码和响应内容。

您可以在 request 方法中传递诸如 headersdataparams 等可选参数来定制您的请求。例如:

response = http.request('POST', url,
                            headers={'Content-Type': 'application/json'},
                            body=json.dumps({"name": "小明", "age": 18}).encode(),
                            )
连接池管理

就像上面示例中创建了一个 PoolManager 一样,urllib3 中的连接池非常强大且灵活。您可以轻松地调整连接池的大小,并在整个应用程序或模块中进行共享。

一个常见的模式是在模块中创建一个连接池,并在所有函数之间共享它。下面是一个简单的示例:

import urllib3

http = urllib3.PoolManager(num_pools=2, maxsize=10)

def foo():
    r = http.request('GET', 'https://www.google.com.hk/')
    print(r.status)
    print(r.data.decode())

def bar():
    r = http.request('GET', 'https://www.google.com.hk/')
    print(r.status)
    print(r.data.decode())

连接池通过 num_poolsmaxsize 参数进行配置。这两个参数决定了连接池的最大数量和每个连接池中连接的最大数量。

如果您需要管理多个连接池,可以使用 PoolManager 的子类来做到这一点。例如,您可以创建不同的连接池以与不同的主机进行通信:

class MyPoolManager(urllib3.PoolManager):
    def __init__(self, *args, **kwargs):
        self.host_map = {}
        super().__init__(*args, **kwargs)

    def request(self, method, url, *args, **kwargs):
        parsed_url = urllib3.util.parse_url(url)
        host = parsed_url.host
        if host not in self.host_map:
            self.host_map[host] = self._new_pool(host)
        return self.host_map[host].request(method, url, *args, **kwargs)

    def _new_pool(self, host):
        return urllib3.PoolManager().ConnectionPool(host)

http = MyPoolManager()
高级功能

在默认情况下,urllib3 提供的连接池只返回存活的连接。如果您想自定义连接管理,例如超时或升级到WebSocket等高级协议,则可以使用两个功能:urllib3.util.retryurllib3.util.Timeout

例如,以下代码说明了如何定义包装器以使用重试和超时功能:

import logging
import urllib3
from urllib3.util.retry import Retry
from urllib3.util.timeout import Timeout

logging.basicConfig()
logger = logging.getLogger(__name__)

def safe_request(url):
    http = urllib3.PoolManager(
        retries=Retry(
            total=5,
            backoff_factor=0.2,
            status_forcelist=[500, 502, 503, 504],
            method_whitelist=["HEAD", "GET", "OPTIONS"]
        ),
        timeout=Timeout(connect=2.0, read=2.0)
    )
    try:
        r = http.request('GET', url)
        logger.debug('url=%s status=%s', url, r.status)
        return r.data
    except Exception as e:
        logger.debug('url=%s error=%r', url, e)
        return None

在上面的示例中,我们使用了 RetryTimeout 来为请求增加保护措施。如果请求失败,则会重试共 5 次。如果在2秒内未与服务器建立连接或读取数据,则会超时。