HTTP 请求与 API:让程序上网冲浪
什么是 API?
你去餐厅吃饭,不会跑到厨房自己炒菜。你做的是:看菜单,选好菜,告诉服务员,然后服务员把菜从厨房端给你。
API(Application Programming Interface)就是程序世界的"菜单 + 服务员"。
- 菜单 = API 文档(告诉你有什么功能、怎么用)
- 点菜 = 发送请求(告诉服务器你想要什么)
- 上菜 = 返回响应(服务器把数据端给你)
你不需要知道"厨房"里是怎么做的,只要按照菜单点菜就行。这就是 API 的精髓——封装复杂性,暴露简单接口。
HTTP 请求基础
互联网上绝大多数 API 都基于 HTTP 协议。你每次打开网页,浏览器其实就在不停地发 HTTP 请求。
最常用的两种请求方法:
| 方法 | 用途 | 生活比喻 |
|---|---|---|
| GET | 获取数据 | 去图书馆借书(我要看看有什么) |
| POST | 提交数据 | 去邮局寄快递(我要发送东西) |
还有 PUT(修改数据)、DELETE(删除数据)等,但 GET 和 POST 覆盖了 80% 的场景。
发送 GET 请求
| Python (requests) | JavaScript (fetch) | |
|---|---|---|
| 安装 | pip install requests | 内置(Node 18+ / 浏览器) |
| 发请求 | requests.get(url) | await fetch(url) |
| 状态码 | response.status_code | response.status |
| 解析 JSON | response.json() | await response.json() |
| 查询参数 | params={"k": "v"} | URLSearchParams 拼到 URL |
Python 的
requests库号称"HTTP for Humans"(人类用的 HTTP 库),API 设计极其简洁直观。JS 的fetch原生支持,但需要搭配async/await使用。
发送 POST 请求
GET 是"拿数据",POST 是"送数据"。比如注册账号、提交表单、发消息等场景:
| Python | JavaScript | |
|---|---|---|
| POST 请求 | requests.post(url, json=data) | fetch(url, { method: "POST", body: JSON.stringify(data) }) |
| 设置请求头 | headers={"K": "V"} | headers: {"K": "V"} |
| 发送 JSON | json=data(自动序列化) | body: JSON.stringify(data)(手动序列化) |
注意 Python 的 requests.post(url, json=data) 有多方便——传 json= 参数会自动把字典序列化成 JSON 字符串,还自动设置 Content-Type 请求头。JS 的 fetch 就没这么贴心了,得自己来。
HTTP 状态码
每次服务器回应你,都会带一个"状态码"告诉你结果如何:
| 状态码 | 含义 | 生活比喻 |
|---|---|---|
| 200 | OK,成功 | "菜来了,请享用" |
| 201 | Created,创建成功 | "您的订单已提交" |
| 400 | Bad Request,请求有误 | "你点的菜菜单上没有" |
| 401 | Unauthorized,未认证 | "请先出示会员卡" |
| 403 | Forbidden,无权限 | "VIP 包间不对外开放" |
| 404 | Not Found,找不到 | "这道菜已经下架了" |
| 500 | Server Error,服务器挂了 | "厨房着火了,暂停营业" |
Python 的
requests不会因为 4xx/5xx 状态码自动抛异常,需要手动检查或调用response.raise_for_status()。JS 的fetch也一样——它只在网络错误时才会 reject,4xx/5xx 只是response.ok为false。这是新手常踩的坑。
REST API 入门
现代 Web API 大多遵循 REST(Representational State Transfer)风格。简单说就是用 HTTP 方法 + URL 路径来表达操作:
| 操作 | HTTP 方法 | URL 示例 | 含义 |
|---|---|---|---|
| 获取所有用户 | GET | /api/users | 列出用户 |
| 获取单个用户 | GET | /api/users/123 | 查看 ID=123 的用户 |
| 创建用户 | POST | /api/users | 新增一个用户 |
| 修改用户 | PUT | /api/users/123 | 更新 ID=123 的用户 |
| 删除用户 | DELETE | /api/users/123 | 删除 ID=123 的用户 |
这种设计就像图书馆的管理规则:
- GET = 查书(只看不碰)
- POST = 捐书(增加新书)
- PUT = 换书(替换旧版)
- DELETE = 撤书(移除下架)
URL 路径表示"资源",HTTP 方法表示"对这个资源做什么"。一目了然。
问 AI:"RESTful API 的设计理念是什么?为什么要把 URL 当作'资源',用 HTTP 方法表示'动作'?跟传统的 RPC 风格有什么区别?"
这个问题会帮你理解 REST 不只是一种写法,更是一种设计哲学。互联网上大多数你能接触到的 API(微信开放平台、GitHub API、各种云服务)都遵循这个理念。
异步请求:Python vs JS 的哲学差异
在网络请求这个领域,两种语言的"性格差异"体现得淋漓尽致:
- Python:默认同步(一步一步来),想异步要额外努力
- JavaScript:天生异步(不等结果就继续),想同步反而麻烦
JS 的
Promise.all()可以同时发起多个请求,总耗时取决于最慢的那个。Python 同步模式下只能一个接一个,总耗时是所有请求之和。这就是为什么 Node.js 在处理大量 I/O 操作(比如 Web 服务器同时服务千百个用户)时表现出色。
CORS——前端开发者的噩梦
如果你在浏览器里用 fetch 调用别人的 API,很可能会看到这个错误:
Access to fetch at 'https://api.xxx.com' from origin 'http://localhost:3000'
has been blocked by CORS policy
这就是 CORS(跨域资源共享)。浏览器出于安全考虑,默认不允许网页向其他域名发请求。
解决方案:
- 后端配置 CORS 头(
Access-Control-Allow-Origin) - 用后端做代理转发
- 开发时用代理工具
注意:Python 的 requests 和 Node.js 脚本不受 CORS 限制,因为 CORS 是浏览器的安全策略,不是 HTTP 协议本身的限制。所以同样的代码在 Node.js 里跑没问题,放到浏览器就报错——这不是 bug,是"feature"。
实战:调用公共 API
互联网上有很多免费的公共 API 可以练手。来看几个好玩的:
毕业项目时间!选一个公共 API,写一个有用的小工具:
推荐的免费 API:
- GitHub API:
https://api.github.com(无需认证即可访问公开数据) - JSONPlaceholder:
https://jsonplaceholder.typicode.com(模拟 REST API,适合练手) - Open Meteo 天气:
https://api.open-meteo.com(免费天气数据)
挑战任务:
- 选一个 API,用 Python 的
requests获取数据 - 用同样的 API,用 JS 的
fetch获取数据 - 把获取到的数据格式化输出
- 把结果保存到 JSON 文件(结合上一节的知识)
比如:写一个"GitHub 仓库探索器",输入一个关键词,搜索相关仓库并显示名称、星标数和描述,然后把结果保存到本地 JSON 文件。
这个练习综合了本章学到的所有知识——文件、JSON、HTTP。完成它,你就真正学会了"让程序与世界对话"!
小结
| 概念 | Python | JavaScript |
|---|---|---|
| HTTP 库 | requests(需安装) | fetch(内置) |
| GET 请求 | requests.get(url) | await fetch(url) |
| POST 请求 | requests.post(url, json=data) | await fetch(url, {method: "POST", body: ...}) |
| 状态码 | response.status_code | response.status |
| 解析 JSON | response.json() | await response.json() |
| 请求头 | headers={...} | headers: {...} |
| 超时设置 | timeout=5 | AbortSignal.timeout(5000) |
| 同步/异步 | 默认同步 | 天生异步 |
一句话总结:Python 的 requests 简单直白——发请求、拿结果、处理数据,三步搞定。JS 的 fetch 需要搭配 async/await,写起来稍微啰嗦,但天生支持并发,在处理大量网络请求时效率更高。两种语言各有所长,学会了都能让你的程序从"单机游戏"变成"联网游戏"。