调你的第一个 API
昨天(Day 06)你学会了用命令行和 Git 管理代码;今天学怎么让你的程序"打电话"给别人的服务器——这就是"调 API"。搞懂 HTTP、JSON、requests 这三件套,明天(Day 08)就能理解"为什么调 API 要用异步",也为后面调大模型 API 打下地基。
为什么转行 Agent 要先学"调 API"
后面 60 天你几乎每天都在做同一件事:把数据打包成请求发出去、把返回的结果解析出来用。RAG 要调 embedding API,工具调用要调外部服务 API,部署后你的 Agent 本身也是一个 API。所以今天是整条路线的地基——它不难,但绕不过去。
HTTP 是什么:一问一答的规矩
一次请求里主要装 4 样东西:
- 方法(Method):你想干嘛(取数据?提交数据?)——下节讲;
- URL(网址):找哪家店、哪张桌
https://api.example.com/weather?city=北京; - 请求头(Headers):附带说明,比如"我是谁"(身份/API Key)、"我要 JSON 格式";
- 请求体(Body):要提交的具体内容(点单的详细内容),只有 POST 这类才有。
常用方法:GET 取、POST 交
| 方法 | 用途(一句话) | 点餐类比 |
|---|---|---|
| GET | 取数据,不改变服务器上的东西 | 看菜单、查今天的菜价 |
| POST | 提交数据,新建一条东西 | 下一个新订单 |
| PUT | 整体更新一条已有数据 | 把整张订单改掉重下 |
| DELETE | 删除一条数据 | 取消订单 |
新手 90% 的时间只会用到 GET 和 POST。规律:只是"要点信息"用 GET,"提交内容让服务器处理"用 POST。调大模型属于后者——你把问题(内容)提交上去让它生成回答,所以是 POST。
GET https://api.xxx.com/weather?city=北京,参数直接挂在网址 ? 后面。提交一条留言(新建内容)→
POST https://api.xxx.com/comments,内容放在"请求体"里,网址上看不到。
状态码:这一单成了没
| 状态码 | 含义 | 点餐类比 |
|---|---|---|
| 200 OK | 成功,数据在响应里 | 菜做好了,端上来了 |
| 201 Created | 成功创建了一条新数据(常见于 POST) | 新订单已建好 |
| 400 Bad Request | 你的请求写错了(参数缺失/格式错) | 你点的菜没写清楚 |
| 401 Unauthorized | 没带身份 / API Key 错了 | 没出示会员卡 |
| 404 Not Found | 网址指向的东西不存在 | 菜单上没这道菜 |
| 429 Too Many Requests | 你请求太频繁,被限流了 | 你一分钟催了 100 次,被叫停 |
| 500 Server Error | 服务器自己出错了(不怪你) | 后厨着火了 |
👶 小白:我调大模型报了 401,是我代码写错了吗?
👨🏫 老师:401 几乎总是"身份没对上"——要么忘了带 API Key,要么 Key 写错/过期/没充值。先别改逻辑,去 L07 检查 Key。反过来 500 大多不怪你,是服务器临时抽风,隔几秒重试常常就好;429 则是你太频繁,要放慢或加重试等待。先看状态码首位,能省你一半排查时间。
JSON:数据的"标准餐盒"
JSON 只有几种积木:对象 {...}(键值对,像字典)、数组 [...](列表)、字符串 "..."、数字、true/false、null。看一眼就懂:
{
"city": "北京",
"temperature": 28,
"is_sunny": true,
"forecast": ["晴", "多云", "小雨"]
}
Python 里用内置的 json 模块互转(不过下一节的 requests 会帮你自动做):
import json # Python 自带,不用安装
# 字符串(JSON) → Python 字典,叫“解析/反序列化”
s = '{"city": "北京", "temp": 28}'
data = json.loads(s) # loads = load string
print(data["city"]) # 北京 ← 像字典一样取值
# Python 字典 → 字符串(JSON),叫“序列化”,准备发出去
d = {"city": "上海", "temp": 30}
print(json.dumps(d, ensure_ascii=False)) # {"city": "上海", "temp": 30}
# ensure_ascii=False 让中文正常显示,而不是变成 \u...
loads 带 s = 从 String 读进来;dumps 带 s = 倒成 String 发出去。方向别搞反。requests:三行调通一个 API
requests 是 Python 最常用的 HTTP 库——它就是你专属的那位服务员:你告诉它"去哪家店、点什么",它跑腿发请求、把菜端回来。先装它:pip install requests。GET 取数据(这里用一个公开的免费测试 API,能真的跑):
import requests # 上面 pip install 过
# 向一个公开测试服务要一条假数据(无需 Key,可直接跑)
resp = requests.get("https://httpbin.org/get", params={"city": "北京"})
# └ 方法 └ 网址(URL) └ params 会自动拼成 ?city=北京
print(resp.status_code) # 200 ← 先看状态码(L04)
data = resp.json() # 自动把返回的 JSON 解析成字典(省了 json.loads)
print(data["args"]) # {'city': '北京'} ← 服务器把我们传的参数原样回显
POST 交数据(提交一段内容,最接近之后调大模型的写法):
import requests
payload = {"question": "你好,今天天气如何?"} # 要提交的内容(字典)
resp = requests.post(
"https://httpbin.org/post",
json=payload, # 用 json= ,requests 自动序列化+设好请求头
timeout=10, # 关键!最多等 10 秒,否则网络卡住会一直挂着
)
resp.raise_for_status() # 若状态码是 4xx/5xx,这里直接抛错,提前发现问题
print(resp.json()["json"]) # {'question': '你好,今天天气如何?'}
timeout,不然请求可能永远卡住;② POST 传字典用 json=(不是 data=)最省事;③ 拿到响应先看 status_code 或用 raise_for_status(),别默认它一定成功。requests.post(url, json={"question":"..."}) = 你对服务员说"我要下单,内容是这句话";返回的
resp.status_code == 200 = 服务员说"做好了";resp.json() = 你打开餐盒,把里面的菜(数据)拿出来吃。之后调 Claude / OpenAI,几乎就是这段的翻版,只是换个网址、加个 Key。
API Key:会员卡,千万别泄露
import requests
api_key = "sk-你的密钥" # 先别急,下面讲更安全的存法
headers = {"Authorization": f"Bearer {api_key}"} # 放在请求头,Bearer 是常见格式
resp = requests.get("https://api.example.com/data", headers=headers, timeout=10)
# 如果 Key 没带对,服务器会回 401(还记得吗?= 没出示会员卡)
最重要的一条安全铁律:绝不把 Key 直接写死在代码里、更不能提交到 GitHub。泄露的 Key 会被别人盗刷,账单能到几千块。正确做法是放进环境变量,代码只去"读"它:
# 在终端里设置环境变量(临时,当前窗口有效)
export API_KEY="sk-你的真实密钥"
# 更常用:把它写进项目根目录的 .env 文件(记得把 .env 加进 .gitignore!)
import os
api_key = os.environ["API_KEY"] # 从环境变量读取,代码里不出现真实密钥
# 或用 os.getenv("API_KEY") ——读不到时返回 None 而不报错,可自行判断
if not api_key:
raise RuntimeError("没找到 API_KEY,请先 export 或写进 .env")
👶 小白:为什么不能图省事直接把 Key 写代码里?就我自己电脑跑而已。
👨🏫 老师:因为你迟早会 git push 到 GitHub。全网有机器人 7×24 小时扫描公开仓库里的 Key,泄露常在几分钟内就被盗刷。用环境变量后,代码可以随便分享,密钥留在你自己机器上——这是所有公司的标配习惯,面试也会问。养成"密钥永不进代码"的肌肉记忆。
今日小结 + 动手 10 分钟
🧠 今天你应该能回答
- 调 API 为什么是学大模型的第一步?(大模型就是别人服务器上的服务,只能通过 API 用)
- HTTP 的基本模式是什么?(客户端发请求、服务器回响应,一问一答)
- GET 和 POST 分别什么时候用?(取信息用 GET,提交内容用 POST;调大模型是 POST)
- 状态码 200 / 401 / 404 / 429 / 500 各代表啥?(成功 / 没带对 Key / 不存在 / 太频繁 / 服务器出错)
- 为什么 API Key 不能写进代码?该放哪?(会被盗刷,放环境变量/.env)
✋ 动手:10 分钟调通一个真实 API
下面这段无需任何 Key,直接能跑,帮你把今天全部概念串一遍:
# 1. 装库(只需一次)
pip install requests
# 2. 存成 first_api.py 后运行: python first_api.py
import requests
# —— GET:向公开测试服务要数据 ——
r = requests.get("https://httpbin.org/get",
params={"name": "转行第7天"}, timeout=10)
print("状态码:", r.status_code) # 期望 200
print("服务器收到的参数:", r.json()["args"]) # {'name': '转行第7天'}
# —— POST:提交一段内容(模拟给大模型发问题)——
r2 = requests.post("https://httpbin.org/post",
json={"question": "HTTP 是什么?"}, timeout=10)
r2.raise_for_status() # 不是 2xx 就报错
print("服务器收到的内容:", r2.json()["json"])# {'question': 'HTTP 是什么?'}
进阶挑战:把网址故意改成 https://httpbin.org/status/404,再打印 status_code,亲眼看看 404 长什么样,然后想想它对应"点餐"里的哪一幕。