
1. 为什么选择requests模块做接口自动化在Python生态中处理HTTP请求的库至少有十几种选择但requests能成为事实上的标准库绝非偶然。我2016年第一次用urllib2做爬虫时光是处理一个带cookie的POST请求就写了20多行代码而用requests只需要3行。这种开发效率的差距在接口自动化测试这种需要高频发送请求的场景下会被放大十倍不止。requests的核心优势在于人性化的API设计response requests.get(url)这种近乎自然语言的写法让代码可读性大幅提升完善的会话管理自动处理cookies、连接池等底层细节不像urllib需要手动维护丰富的功能支持从基础认证到文件上传覆盖了90%的HTTP使用场景活跃的社区生态GitHub上48k的star和8k的fork意味着遇到问题随时能找到解决方案提示虽然Python标准库有urllib3但在实际接口测试中除非有特殊需求如需要精细控制HTTP连接池否则直接使用requests是更明智的选择。2. GET请求的完整参数解析2.1 基础GET请求实现先看最简单的GET请求示例import requests response requests.get(https://api.github.com/events) print(response.status_code) # 200 print(response.text[:100]) # 查看前100个字符这个例子虽然简单但隐藏了几个关键知识点自动解码response.text会根据响应头自动处理编码如UTF-8连接复用底层使用urllib3的连接池相同host的请求会复用TCP连接超时机制默认没有设置超时这在生产环境是危险的后面会讲如何正确设置2.2 带参数的GET请求实际接口测试中90%的GET请求都需要携带参数。requests提供了两种传参方式方式一手动拼接URL不推荐url https://httpbin.org/get?key1value1key2value2 response requests.get(url)方式二使用params参数推荐params {key1: value1, key2: [value2, value3]} response requests.get(https://httpbin.org/get, paramsparams)第二种方式的优势在于自动处理URL编码比如空格转%20支持列表参数如上例中的value2和value3会变成key2value2key2value3代码可读性更好参数与URL分离2.3 请求头定制接口测试经常需要设置User-Agent、Content-Type等头部信息headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64), Accept: application/json } response requests.get(https://httpbin.org/headers, headersheaders)实测中发现三个易错点Header名称大小写HTTP协议规定header名不区分大小写但某些服务端实现会有要求默认User-Agentrequests默认的UA是python-requests/2.31.0容易被某些网站屏蔽Content-Type陷阱GET请求通常不需要设置但某些特殊API可能有要求3. 实战中的高级技巧3.1 超时控制与重试机制我曾在生产环境遇到因未设置超时导致线程挂起的严重事故。正确的超时设置应该是try: response requests.get(https://httpbin.org/delay/5, timeout(3.05, 27)) except requests.exceptions.Timeout: print(请求超时)这里的timeout参数有两个值第一个3.05秒是连接超时建议比3的整数倍稍大避免TCP重传定时器干扰第二个27秒是读取超时根据业务响应时间合理设置对于429 Too Many Requests错误常见于爬虫场景可以这样实现自动重试from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry session requests.Session() retries Retry(total3, backoff_factor1, status_forcelist[429, 502, 503, 504]) session.mount(https://, HTTPAdapter(max_retriesretries)) response session.get(https://httpbin.org/status/429)3.2 代理配置与SSL验证在企业内网测试时经常需要配置代理proxies { http: http://10.10.1.10:3128, https: http://10.10.1.10:1080, } requests.get(http://example.org, proxiesproxies)遇到自签名证书报错时常见于测试环境可以这样处理# 临时关闭验证不安全仅限测试环境 requests.get(https://self-signed.badssl.com, verifyFalse) # 添加自定义CA证书 requests.get(https://self-signed.badssl.com, verify/path/to/cert.pem)3.3 响应处理最佳实践很多新手会直接使用response.text这其实存在隐患。更健壮的做法是response requests.get(https://api.github.com/events) # 检查状态码 response.raise_for_status() # 非2xx会抛出异常 # 智能解码内容优先用response.json()处理JSON数据 try: data response.json() except ValueError: data response.content # 二进制数据 # 或者 response.text # 文本数据我总结的响应处理黄金法则永远先检查状态码或调用raise_for_statusJSON响应优先用response.json()解析大文件下载用response.iter_content()分块读取4. 企业级接口测试实战4.1 封装可复用的请求工具类在实际项目中我会这样封装GET请求class ApiClient: def __init__(self, base_url): self.session requests.Session() self.base_url base_url self.session.headers.update({User-Agent: MyApiClient/1.0}) def get(self, endpoint, paramsNone, **kwargs): url f{self.base_url}/{endpoint} try: response self.session.get( url, paramsparams, timeout10, **kwargs ) response.raise_for_status() return response.json() except requests.exceptions.RequestException as e: print(f请求失败: {e}) raise # 使用示例 client ApiClient(https://api.example.com/v1) data client.get(users, params{active: True})这种封装带来了三个好处统一管理基础URL和公共headers内置异常处理和日志记录一致的超时和重试策略4.2 结合pytest做自动化测试实际项目中GET请求测试可以这样写import pytest pytest.mark.parametrize(user_id,expected_status, [ (1, 200), (999, 404), (invalid, 400) ]) def test_get_user(user_id, expected_status): response requests.get(fhttps://api.example.com/users/{user_id}) assert response.status_code expected_status if response.status_code 200: assert username in response.json()4.3 性能优化技巧当需要批量发送GET请求时同步请求效率很低。这时可以用import concurrent.futures urls [ https://httpbin.org/get?page1, https://httpbin.org/get?page2 ] def fetch(url): return requests.get(url).json() with concurrent.futures.ThreadPoolExecutor(max_workers5) as executor: results list(executor.map(fetch, urls))但要注意线程数不要超过目标服务器的承受能力考虑使用timeout参数避免单个请求拖慢整体对于特别大量的请求建议使用aiohttp等异步库5. 常见问题排查手册5.1 SSL证书验证失败错误信息SSLError: HTTPSConnectionPool...certificate verify failed解决方案# 临时方案测试环境 requests.get(url, verifyFalse) # 长期方案 import certifi requests.get(url, verifycertifi.where())5.2 编码问题导致乱码现象response.text返回乱码正确处理方式# 方式1手动指定编码 response.encoding gbk print(response.text) # 方式2使用二进制内容自行解码 content response.content print(content.decode(gb18030))5.3 连接池耗尽问题现象ConnectionError: HTTPSConnectionPool...Max retries exceeded解决方案# 增加连接池大小 from requests.adapters import HTTPAdapter session requests.Session() adapter HTTPAdapter(pool_connections50, pool_maxsize50) session.mount(https://, adapter)5.4 处理gzip压缩响应有些服务器会返回gzip压缩内容requests默认会自动解压但偶尔会遇到问题# 手动处理gzip import gzip from io import BytesIO if response.headers.get(Content-Encoding) gzip: buf BytesIO(response.content) decompressed gzip.GzipFile(fileobjbuf).read() print(decompressed.decode())