童话故事集 API:故事列表搜索与分页实战(1700-2,classifyId + keyword)
# 童话故事集 API:故事列表搜索与分页实战(1700-2,classifyId + keyword)
> 元信息:童话故事集 API(apiCode=1700)· 接入点 1700-2 · 免费服务 · 返回 JSON · 适用人群:需做故事检索/翻页的开发者 · 阅读时间约 7 分钟
## 核心要点
- 1700-2 必填两项:`classifyId`(来自 1700-1)与 `keyword`(标题关键字);`page` 可选,默认第 1 页。
- 分页看四个字段:`allNum`(总数)、`allPages`(总页数)、`currentPage`(当前页)、`maxResult`(单页上限,默认 20)。
- `keyword` 必填但文档未给"查全部分类"的空值约定,不要臆造空串/通配行为,建议实测。
## Why:列表是产品的核心页面
用户进到一个故事 App,通常会先看到"某一分类下有哪些故事"的列表,再点进去看详情。1700-2 就是取这个列表的接口:支持按分类 + 关键字检索,并自带分页信息。本篇讲清参数组合、分页翻页,以及那个容易踩的 `keyword` 必填坑。
## What:接口速览
| 项目 | 说明 |
|------|------|
| 接口地址 | `https://route.showapi.com/1700-2?appKey=YOUR_APPKEY` |
| 必填参数 | `classifyId`(分类 Id)、`keyword`(标题关键字) |
| 可选参数 | `page`(页码,默认 1) |
| 返回数组 | `showapi_res_body.contentlist[]` |
| 计费 | 免费 |
## How:组合参数取列表 + 翻页
```python
import requests
APPKEY = "YOUR_APPKEY"
url = f"https://route.showapi.com/1700-2?appKey={APPKEY}"
def fetch_page(classify_id, keyword, page=1):
r = requests.post(url, data={"classifyId": classify_id, "keyword": keyword, "page": str(page)},
headers={"content-type": "application/x-www-form-urlencoded"}, timeout=10)
body = r.json()["showapi_res_body"]
if body.get("ret_code") != "0":
raise SystemExit(body.get("remark"))
return body
body = fetch_page("1", "妈妈", 1)
print("总数:", body["allNum"], "总页:", body["allPages"])
for item in body["contentlist"]:
print(item["id"], item["title"])
```
```bash
curl -X POST "https://route.showapi.com/1700-2?appKey=YOUR_APPKEY" \
-H "content-type: application/x-www-form-urlencoded" \
-d "classifyId=1&page=1&keyword=%E5%A6%88%E5%A6%88"
```
```javascript
const r = await fetch(`https://route.showapi.com/1700-2?appKey=YOUR_APPKEY`, {
method: "POST",
headers: { "content-type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({ classifyId: "1", keyword: "妈妈", page: "1" }),
});
const body = (await r.json()).showapi_res_body;
console.log("总数", body.allNum, "总页", body.allPages);
for (const it of body.contentlist) console.log(it.id, it.title);
```
### 翻页写法
`page` 从 1 递增到 `allPages` 即可拉全:
```python
all_pages = int(body["allPages"])
for p in range(2, all_pages + 1):
body = fetch_page("1", "妈妈", p)
# 继续处理 contentlist ...
```
## 返回示例与解析
```json
{
"showapi_res_body": {
"remark": "查询成功!",
"allPages": 1,
"ret_code": 0,
"contentlist": [
{ "id": "5ba1c830c1b4f34642f5e66a", "title": "谜语童话", "classifyId": "3" },
{ "id": "5ba1c5dbc1b4be0a124a844c", "title": "老橡树的最后一梦(圣诞童话)", "classifyId": "2" }
],
"currentPage": 1,
"allNum": 15,
"maxResult": 20
}
}
```
| 字段 | 含义 |
|------|------|
| `contentlist[].id` | 故事 id,传给 1700-3 取详情 |
| `contentlist[].title` | 故事名 |
| `contentlist[].classifyId` | 分类 Id |
| `allNum / allPages / currentPage / maxResult` | 分页信息 |
## 进阶 / 边界
- **`keyword` 必填的坑**:文档明确 `keyword` 为必填。这意味着即使只想"按分类浏览全部",也必须传 `keyword`。但"查全部分类"该传什么值(空串?`*`?),文档未给约定——**不要臆造**,建议实测或先用具体关键字。
- **数组名为 `contentlist`**:与 1700-1 的 `storylist` 不同,注意区分(详见[返回字段全解](https://www.showapi.com/guides/child-story-fields-1700))。
- **maxResult 默认 20**:单页上限,无自定义参数,靠 `page` 翻页取到 `allPages` 为止。
## FAQ
**Q: 我只想按分类列出所有故事,不想搜关键字,怎么传 keyword?**
A: 文档规定 keyword 必填且未给"查全部"的空值约定,请勿硬编码空串/通配。稳妥做法是用一个能命中该分类的关键字,或等官方明确行为后处理。
**Q: 分页怎么判断拉完了?**
A: 当 `currentPage == allPages` 时即为最后一页,或循环 `page` 从 1 到 `int(allPages)`。
**Q: 为什么我传了 classifyId 还是报错?**
A: 大概率是 `keyword` 没传或为空。1700-2 的 `classifyId` 与 `keyword` 都是必填,二者都要给。
**Q: 列表里没有故事正文,怎么看全文?**
A: 用 `contentlist[].id` 调 1700-3 故事详情接口取 `content`。
## 相关能力 / 下一步阅读
- [童话故事集 API:故事详情接入点怎么用](https://www.showapi.com/guides/child-story-detail-guide-1700)
- [童话故事集 API:故事分类接入点怎么用](https://www.showapi.com/guides/child-story-classify-guide-1700)
- [免费接口也别乱调用:内容缓存与分页拉取策略](https://www.showapi.com/guides/child-story-cache-1700)
- **本系列共 12 篇**:查看[童话故事集 API 指南总目录](https://www.showapi.com/guides/child-story-guides-1700)