十万个为什么 API:列表→详情两接入点串联的全链路设计
十万个为什么 API列表详情串联全链路设计科普问答免费接口 # 十万个为什么 API:列表→详情两接入点串联的全链路设计
> 接口:十万个为什么(apiCode=1706)· 接入点:列表(1706-1) → 详情(1706-2) · 免费 · 请求方式:POST/GET · 返回格式:JSON · 适用人群:全栈工程师 / 产品经理 · 阅读时间:约 8 分钟
## 核心要点
- 本接口是「两段式」设计:列表只给 `id`+`title`,详情才给 `content`,二者必须串联使用。
- 推荐把列表结果落库(存 `id` 与 `title`),用户点开某条时再按需调详情,避免一次性拉取全部正文。
- 时序清晰:关键词入参 → 列表拿 id → 用户选择 → 详情取内容 → 前端渲染。
## Why:为什么是两段式而不是一个接口返回全部
如果列表就把所有正文都返回,一次查询 210 条(示例 `allNum`)的正文会非常臃肿,绝大多数用户只看其中一两条。拆成「列表轻量 + 详情按需」既省流量也契合免费接口的档位限制。理解了这点,你的数据表和点流程才好设计。
## What:接口速览
| 项 | 列表(1706-1) | 详情(1706-2) |
|----|------|------|
| 入参 | `keyword`(必填)、`page` | `id`(必填) |
| 出参 | `contentlist[{id,title}]` + 分页 | `title`、`content` |
| 角色 | 搜索 / 浏览 | 查看单条 |
## How:全链路实现
**步骤 1 — 数据表设计**
只需两张轻量表,或一张带状态字段的表:
```sql
-- 问题列表(来自列表接入点)
CREATE TABLE why_question (
id VARCHAR(32) PRIMARY KEY, -- 详情接入点的入参
title VARCHAR(255),
keyword VARCHAR(64), -- 检索词,便于复用
page INT
);
-- 详情内容(懒加载,点开才填)
CREATE TABLE why_content (
id VARCHAR(32) PRIMARY KEY,
title VARCHAR(255),
content TEXT,
fetched_at DATETIME
);
```
**步骤 2 — 时序(用户视角)**
```
用户输入关键词 ──▶ 调列表(1706-1) ──▶ 展示 title 列表
│ │
│ 用户点击某条
│ ▼
└──────────────────────────▶ 调详情(1706-2, id) ──▶ 渲染 content
```
**步骤 3 — 串联代码(Python)**
```python
import requests
APP_KEY = "YOUR_APPKEY"
BASE = "https://route.showapi.com"
def search(keyword: str, page: str = "1") -> list:
r = requests.post(f"{BASE}/1706-1", data={"keyword": keyword, "page": page},
params={"appKey": APP_KEY},
headers={"content-type": "application/x-www-form-urlencoded"},
timeout=10).json()
body = r["showapi_res_body"]
if body.get("ret_code") != "0":
raise RuntimeError(body.get("remark"))
return body["contentlist"] # [{id, title}, ...]
def detail(qid: str) -> dict:
r = requests.post(f"{BASE}/1706-2", data={"id": qid},
params={"appKey": APP_KEY},
headers={"content-type": "application/x-www-form-urlencoded"},
timeout=10).json()
body = r["showapi_res_body"]
if body.get("ret_code") != "0":
raise RuntimeError(body.get("remark"))
return {"title": body["title"], "content": body["content"]}
# 用法
for q in search("地球"):
print(q["id"], q["title"])
# 用户点开时:detail(q["id"])
```
## 返回示例与解析
列表返回 `contentlist` 数组(每项 `id`/`title`),详情返回 `title`/`content`。串联关键点:**用列表的 `id` 作为详情的入参**,两者字段名一致。
## 进阶 / 边界
- **懒加载而非预拉取**:不要为每条列表结果提前调详情,按需触发,既快又省档位。
- **缓存 id**:同一关键词的列表结果可缓存(见[《免费档位下:用缓存策略节省调用次数》](https://www.showapi.com/guides/why100k-free-tier-cache-1706))。
- **空结果**:关键词太冷门可能 `contentlist` 为空数组,前端应给"没有找到相关问题"提示。
## FAQ
**Q1:列表能直接返回 content 吗?**
不能。列表只返回 `id`+`title`,正文必须通过详情接入点用 `id` 获取。
**Q2:列表的 id 和详情的 id 是同一个吗?**
是同一个。列表 `contentlist[].id` 直接作为详情入参 `id`。
**Q3:可以并发拉多个详情吗?**
可以,但注意免费档位限制,建议按需串行或加缓存,避免集中打满档位。
**Q4:page 不传会怎样?**
列表 `page` 非必填,不传默认第 1 页(示例默认 "1")。
**Q5:用户点了列表里没有的条目怎么办?**
正常不会,因为 id 来自列表返回;若自行拼接 id,需确保 id 真实存在,否则详情返回失败。
## 相关能力 / 下一步阅读
- [十万个为什么 API 家长辅助教育场景:儿童科学问答小程序集成](https://www.showapi.com/guides/why100k-kids-education-1706)
- [十万个为什么 API:如何优雅展示 title 与 content 科普内容?](https://www.showapi.com/guides/why100k-content-display-1706)
- [十万个为什么 API 免费档位下:用缓存策略节省调用次数](https://www.showapi.com/guides/why100k-free-tier-cache-1706)
- **本系列共 11 篇**:查看[十万个为什么 API 指南总目录](https://www.showapi.com/guides/why100k-guides-1706)