小白python入门 - 34. 用 requests 调外部接口
1. 本课定位是什么、为何重要第 33 课认清了 HTTP 的URL / 方法 / 状态码 / Header / Body。本课把这些约定落成Python 里可维护的客户端代码。概念一句话requests第三方 HTTP 客户端库发请求、收响应比标准库urllib更短、更清晰Response 对象一次调用的结果状态码、头、正文.json()再变成 dict/list为何重要调天气、支付、GitHub、公司内部 API几乎都是「写客户端」写不稳无超时、乱拼密钥、不看状态码会在生产里埋雷。对比已学已学Day33 / urllib本课requests手写Requesturlopen 自己json.loadsrequests.get/postr.json()概念上的五件套五件套对应到函数参数与属性知道要超时强制把timeout写成习惯知道 4xx/5xxraise_for_status/ 异常类型pipinstallrequests2. 本质、约束与常见坑本质一次requests.get/post(...)≈ 组装请求方法、URL、头、体→ 经网络发出 → 得到Response。默认同步阻塞这行不返回后面的代码不会跑这是第 3536 课并发的伏笔。约束必须能访问目标主机证书、代理、防火墙会导致失败。默认不会永远重试失败要你自己处理。对方返回的不一定是 JSON错误页常是 HTML。r.json()得到的是新的Python 对象只存在本机内存不改服务器数据。常见坑坑现象正确做法不写timeout网络卡住时进程挂死几乎每次调用都带timeout只r.json()不看状态码404 HTML 导致 JSON 解析炸先raise_for_status()或判断status_codejson与data混用Content-Type / 服务端解析不对JSON 用json表单常用data密钥写进源码泄露进 Git环境变量 / 配置文件不进仓库在asyncio里直接requests.get堵死事件循环异步用httpx/aiohttp第 36 课无限猛重试打爆对方、自己被封有限次数 间隔尊重 4293. 最小调用GET / POSTimportrequests rrequests.get(https://httpbingo.org/get,params{q:python},timeout20,)print(r.status_code)print(r.json().get(args))r2requests.post(https://httpbingo.org/post,json{name:bob},timeout20,)print(r2.json().get(json)orr2.json().get(data))预期输出形态200 {q: [python]} {name: bob}调用前没有 Response。调用后可读status_code、.text、.json()等。4. 传参对照params / json / data / headers参数数据放哪典型用途paramsURL 查询串GET 过滤、分页jsonBody且设为 JSONPOST/PUT APIdataBody常表单编码传统 formheaders请求头Token、UA、Accepttimeout不是 Body最长等待秒数小对照# 查询串.../get?a1requests.get(url,params{a:1},timeout20)# JSON Bodyrequests.post(url,json{a:1},timeout20)# 表单 Bodyapplication/x-www-form-urlencodedrequests.post(url,data{a:1},timeout20)同一份{a:1}位置不同服务端收到的「槽位」就不同——对应 Day33 的 query vs Body。5. 响应怎么读属性分类类别常用含义状态status_code、ok、raise_for_status()成败与是否抛错头headers对方回的元数据正文text、content、json()字符串 / 字节 / 解析后的对象rrequests.get(https://httpbingo.org/get,params{x:1},timeout20)print(r.status_code,r.ok)r.raise_for_status()datar.json()# 新 dict不是改服务器print(type(data),data.get(args))okvsraise_for_status写法行为if r.ok:2xx 为真自行分支r.raise_for_status()4xx/5xx 抛HTTPError适合「失败就别往下走」6. 能力分组发送 · 稳健 · 会话 · 身份6.1 发送类requests.get/post/put/delete/patch或统一requests.request(GET, url, ...)6.2 稳健类强烈建议形成肌肉记忆try:rrequests.get(url,timeout10)r.raise_for_status()datar.json()exceptrequests.Timeout:print(超时)exceptrequests.HTTPErrorase:print(HTTP 错误,e.response.status_code)exceptrequests.RequestExceptionase:print(网络或请求层错误,e)超时演示访问约 5 秒延迟、timeout2importrequeststry:requests.get(https://httpbingo.org/delay/5,timeout2)exceptrequests.Timeout:print(Timeout)预期输出Timeout重试教学版有限次数 间隔importtimeimportrequests urlhttps://httpbingo.org/status/200forattemptinrange(1,4):resprequests.get(url,timeout15)print(fattempt{attempt}: status{resp.status_code})ifresp.ok:breaktime.sleep(0.5)预期输出attempt 1: status200收到429应降速而不是加大并发硬刚。6.3 会话类 Session每次requests.getSessionCookie默认不跨请求保持可自动保持默认头每次传session.headers.update(...)一次连接相对一次性更易复用性能细节入门了解即可sessionrequests.Session()session.headers.update({User-Agent:python-lab-day34/1.0})rsession.get(https://httpbingo.org/get,params{page:1},timeout20)6.4 身份与密钥importosimportrequests keyos.environ.get(DEMO_API_KEY,)headers{Authorization:fBearer{key}}ifkeyelse{}rrequests.get(https://httpbingo.org/headers,headersheaders,timeout15)错误Authorization Bearer sk-xxxx写死在仓库。正确环境变量注入文档里只写变量名。7. 落地场景故事 写法场景方法关键参数查公开仓库信息GETURL 路径参数 / 查询串提交注册 JSONPOSTjson{...}带令牌访问GET/POSTheadersAuthorization对方偶发 503GET有限重试 timeout教学仍可用回声服务验证「参数有没有发对」真实项目换成业务 Base URL 即可。8. 综合实践一键脚本mkdir-p~/python-lab/src/day34cd~/python-lab/src/day34 pipinstallrequestsWindows 推荐 Cygwin 或 WSL。catrequests_demo.pyEOF # Day34: requests client import os import time import requests def main(): session requests.Session() session.headers.update({User-Agent: python-lab-day34/1.0}) print(--- GET params ---) r session.get( https://httpbingo.org/get, params{q: python, page: 1}, timeout20, ) r.raise_for_status() data r.json() print(status:, r.status_code) print(args:, data.get(args)) print(--- POST json ---) r2 session.post( https://httpbingo.org/post, json{name: bob, role: student}, timeout20, ) r2.raise_for_status() body r2.json() print(echo:, body.get(json) or body.get(data)) print(--- timeout demo ---) try: session.get(https://httpbingo.org/delay/5, timeout2) except requests.Timeout: print(Timeout:, Timeout) print(--- retry pattern ---) for attempt in range(1, 4): resp session.get(https://httpbingo.org/status/200, timeout15) print(fattempt {attempt}: status{resp.status_code}) if resp.ok: break time.sleep(0.3) key os.environ.get(DEMO_API_KEY, ) print(--- auth header style ---) print(DEMO_API_KEY set:, bool(key)) headers {} if key: headers[Authorization] fBearer {key} r3 session.get(https://httpbingo.org/headers, headersheaders, timeout15) r3.raise_for_status() hdrs r3.json().get(headers) or {} has_auth any(k.lower() authorization for k in hdrs) print(Authorization in request:, has_auth or bool(key)) if __name__ __main__: main() EOFpython3 requests_demo.py实测输出--- GET params --- status: 200 args: {page: [1], q: [python]} --- POST json --- echo: {name: bob, role: student} --- timeout demo --- Timeout: Timeout --- retry pattern --- attempt 1: status200 --- auth header style --- DEMO_API_KEY set: False Authorization in request: False总结与学习路线requests把 Day33 的 HTTP 五件套变成参数与 Response 属性。timeout 状态处理 参数绑定式传参 密钥不进库是客户端底线。Session适合连续调用异步场景不要硬塞同步requests。建议学习路径基础— 会get/post能打印status_code与json操作— 分清params/json/data/headers进阶—raise_for_status、Timeout、有限重试、Session实战— 用环境变量做 Bearer封装小组件get_json(url)思维拔高好的客户端默认不信任网络——任何远程调用都可能慢、失败、返回怪数据。下一课并发模型怎么选多个请求如何重叠等待。文档Requests: HTTP for Humans小练笔题 1为什么几乎总要设置timeout题 2params{a: 1}和json{a: 1}区别题 3判断把 API Key 写进源码提交到 Git 是好习惯。题 4r.ok与r.raise_for_status()使用上的主要差别题 5判断r.json()会修改服务器上的数据。小练笔参考答案题 1避免网络异常时程序无限等待。题 2params进入 URL 查询串json进入请求 BodyJSON并带合适 Content-Type。题 3错。题 4ok只给布尔值由你分支raise_for_status在 4xx/5xx 时直接抛HTTPError。题 5错。只是把响应正文解析成本地 Python 对象。