06 Python HTTP 请求入门
Python HTTP 请求入门
一、程序怎么和外界通信
你的 Python 脚本 ──HTTP 请求──▶ 远程服务器(API)
◀──HTTP 响应── 返回 JSON / 文本
二、requests 入门
安装 requests
requests 是 Python 最常用的 HTTP 库,语法简单
项目根目录下,先激活虚拟环境,再安装:
cd D:\test\python_study
python -m venv .venv
.venv\Scripts\activate
pip install requests
验证:
python -c "import requests; print(requests.__version__)"
第 1 行:python -m venv .venv
作用:创建虚拟环境
| 部分 | 含义 |
|---|---|
| python | 调用系统里的 Python |
| -m venv | 以模块方式运行 venv(Python 自带的虚拟环境工具) |
| .venv | 在当前目录下创建名为 .venv 的文件夹 |
执行后会在项目根目录生成 .venv/,里面有独立的 Python 和 pip,依赖只装在这个项目里,不影响系统全局 Python。
类比前端: 类似在项目里初始化一个独立的依赖空间(类似有独立 node_modules 的项目环境),而不是用全局安装的包。
第 2 行:.venv\Scripts\activate
作用:激活虚拟环境
执行后,当前终端会「切换」到 .venv 里的 Python 和 pip。成功后提示符前会出现 (.venv)`,例如:
(.venv) PS D:\test\python_study>
第 3 行:pip install requests
作用:在当前环境里安装 requests 这个第三方包
| 部分 | 含义 |
|---|---|
| pip | Python 的包管理器(类似前端的 npm / pnpm) |
| install | 安装依赖(类似 npm install) |
| requests | 要安装的包名,用来发 HTTP 请求 |
前提是你已经激活了虚拟环境(提示符里有 (.venv)),这样包装进项目的 .venv,不会污染全局 Python。
GET 请求的两种传参
| 类型 | 写法 | 例子 |
|---|---|---|
| 路径参数 | 写在 URL 路径里 | /posts/1、/api/voi/123 |
| 查询参数 | 写在 ? 后面(Query String) |
/posts?userId=1 |
前端路由里的 params(如 /api/voi/:id)指的是路径参数;Python requests 里的 params= 指的是查询参数,不要混用。
路径参数:直接拼进 URL
post_id = 1
response = requests.get(f"https://jsonplaceholder.typicode.com/posts/{post_id}")
data = response.json() # 返回 dict,id=1 的那篇文章
查询参数:URL 后面加 ?key=value
https://jsonplaceholder.typicode.com/posts?userId=1
用 params= 传查询参数,更清晰:
response = requests.get(
"https://jsonplaceholder.typicode.com/posts",
params={"userId": 1},
)
print(response.url) # 看最终拼好的 URL
data = response.json() # 返回 list,该用户的所有帖子
推荐的公开测试 API
本课用 JSONPlaceholder — 免费、稳定、无需 API Key:
| 端点 | 说明 |
|---|---|
| GET /posts/1 | 获取 id=1 的文章(返回 dict) |
| GET /posts?userId=1 | 获取 userId=1 的所有文章(返回 list) |
| GET /users/1 | 获取 id=1 的用户信息 |
常见错误
| 错误 | 原因 |
|---|---|
| ModuleNotFoundError: No module named ‘requests’ | 没安装或虚拟环境没激活 |
| ConnectionError | 网络不通或 URL 写错 |
| KeyError | JSON 字段名写错,先用 print(data) 看结构 |
| 不检查 status_code 直接用 .json() | 404/500 时可能解析失败 |
三、POST 请求
发 POST 的几种方式
# 方式 1:发 JSON(推荐,API 最常用)
# json= 会自动做两件事:把 dict 转成 JSON 字符串,并设置 Content-Type: application/json。
requests.post(url, json={"key": "value"})
# 方式 2:手动发 JSON 字符串(需自己设 Content-Type)
# 用 data= 传字符串时,requests 默认是 application/x-www-form-urlencoded(表单编码),需手动设为 JSON。
requests.post(url, data='{"key": "value"}', headers={"Content-Type": "application/json"})
# 方式 3:纯文本
requests.post(url, data='hello world', headers={"Content-Type": "text/plain"})
# 方式 4:表单字段(data 传 dict 时常见)
requests.post(url, data={"key": "value"}) # 默认 application/x-www-form-urlencoded
Header(请求头 / 响应头)
Header 是请求的「元信息」,键值对形式。
常见请求头
| Header | 作用 | 例子 |
|---|---|---|
| Content-Type | Body 是什么格式 | application/json |
| Authorization | 身份认证 | Bearer sk-xxxx(LLM API 常用) |
| User-Agent | 客户端是谁 | MyApp/1.0 |
在 requests 里设置 Header
headers = {"User-Agent": "PythonStudy/1.0"}
response = requests.get(url, headers=headers)
看响应头
print(response.headers) # 全部响应头
print(response.headers.get("Content-Type")) # 常见:application/json; charset=utf-8
HTTP 状态码
| 状态码 | 含义 | 你该怎么想 |
|---|---|---|
| 200 | OK,成功 | 正常处理 response.json() |
| 201 | Created,创建成功 | POST 创建资源时常见 |
| 400 | Bad Request,请求有误 | 检查 Body、参数格式 |
| 401 | Unauthorized,未授权 | 缺 API Key 或 Key 无效 |
| 404 | Not Found,找不到 | URL 或 id 写错(你测过 99990) |
| 500 | Internal Server Error | 服务器内部错误 |
通过 response.status_code 读取。
读响应体
response.text # 字符串(原始文本)
response.json() # 解析成 dict/list(前提是 JSON)
response.content # 二进制 bytes(图片等)
对象属性 和 字典键 的区别
response ← httpx.Response 对象
├── status_code ← 对象的属性(int)
├── headers ← 对象的属性(Headers 映射)
│ └── "Content-Type" ← headers 里的一个键(字符串)
└── ...
四、httpx — API(支持 async/await:)
安装 httpx
环境同上,pip install httpx
保存二进制文件
文本用 write_text(),图片用 write_bytes():
from pathlib import Path
path = Path("downloads/cat.jpg")
path.parent.mkdir(parents=True, exist_ok=True) # 确保目录存在
path.write_bytes(response.content) # 写入二进制
parents=True
自动创建路径上所有缺失的上级目录。
比如:会依次创建:a → a/b → a/b/c。
如果 parents=False(默认),中间缺一层就会报错。
exist_ok=True
目录已经存在时不报错。
exist_ok=False(默认):目录已存在 → 抛 FileExistsError
exist_ok=True:目录已存在 → 静默跳过
常见组合就是「缺啥建啥,有了也不报错」。
httpx 异步下载一张图
import httpx
async def download_image(url: str, save_path: Path) -> bool:
async with httpx.AsyncClient(timeout=30.0) as client:
response = await client.get(url)
if response.status_code == 200:
save_path.write_bytes(response.content)
return True
return False
response.content 是 bytes 类型,正好对应图片二进制数据。
更多推荐


所有评论(0)