古籍查询 API 分页机制:page / maxResult / allPages 怎么用
# 古籍查询 API 分页机制:page / maxResult / allPages 怎么用
> 接口:古籍查询(apiCode 1643)· 接入点 1643-3「查询古籍明细」· **免费服务** · 请求方式 POST/GET · 返回 JSON
> 适用人群:要抓取一部书全部篇章(多页)的开发者 · 阅读时间:约 5 分钟
## 核心要点
- 1643-3 用 `page` 控制页码,`page` 从 1 开始;默认每页 20 条(`maxResult`)。
- 返回里的 `allPages`(总页数)、`allNum`(总篇章数)、`currentPage`(当前页)告诉你还要不要翻页。
- 翻页直到 `currentPage == allPages` 即取完;以《论语》为例,实测 `allNum=20`、`allPages=1`,一页就取完。
## Why:什么时候需要分页?
一部古籍往往有多个篇章(如《论语》20 篇)。1643-3 一次只返回一页(默认 20 条)。如果你要"整本书"的内容,就需要按 `page` 翻完所有页。理解分页字段能让你写出稳定、不漏不重的抓取循环。
## What:分页相关字段
| 字段 | 位置 | 含义 |
|------|------|------|
| `page` | 请求参数(选填) | 页码,从 1 开始;不传默认第 1 页 |
| `maxResult` | 返回 body | 每页条数,默认 20 |
| `allNum` | 返回 body | 该书的篇章总数(本页口径) |
| `allPages` | 返回 body | 总页数 |
| `currentPage` | 返回 body | 本次返回的页码 |
## How:翻页抓取(多语言)
Python(按 allPages 循环):
```python
import requests
APPKEY = "YOUR_APPKEY"
TITLE_ID = "5b23316f618cd77360b91f0d"
url = f"https://route.showapi.com/1643-3?appKey={APPKEY}"
all_chapters = []
page = 1
while True:
body = requests.post(url, data={"titleId": TITLE_ID, "page": str(page)},
headers={"content-type": "application/x-www-form-urlencoded"}, timeout=10
).json()["showapi_res_body"]
if body.get("ret_code") != "0":
raise RuntimeError(body.get("remark"))
all_chapters.extend(body["ancientBooksInfo"])
if body["currentPage"] >= body["allPages"]:
break
page += 1
print(f"共抓到 {len(all_chapters)} 个篇章,总页数 {body['allPages']}")
```
cURL(逐页手动翻):
```bash
# 第 1 页
curl -X POST "https://route.showapi.com/1643-3?appKey=YOUR_APPKEY" \
-H "content-type: application/x-www-form-urlencoded" \
-d "titleId=5b23316f618cd77360b91f0d&page=1"
# 第 2 页(如有)
curl -X POST "https://route.showapi.com/1643-3?appKey=YOUR_APPKEY" \
-H "content-type: application/x-www-form-urlencoded" \
-d "titleId=5b23316f618cd77360b91f0d&page=2"
```
Node.js(fetch,按 allPages 循环):
```javascript
const APPKEY = "YOUR_APPKEY";
const TITLE_ID = "5b23316f618cd77360b91f0d";
const url = `https://route.showapi.com/1643-3?appKey=${APPKEY}`;
const all = [];
let page = 1;
while (true) {
const body = (await (await fetch(url, {
method: "POST",
headers: { "content-type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({ titleId: TITLE_ID, page: String(page) })
})).json()).showapi_res_body;
if (body.ret_code !== "0") throw new Error(body.remark);
all.push(...body.ancientBooksInfo);
if (body.currentPage >= body.allPages) break;
page++;
}
console.log(`共抓到 ${all.length} 个篇章,总页数 ${body.allPages}`);
```
## 返回示例(含分页字段)
```json
{
"showapi_res_body": {
"ret_code": "0",
"remark": "查询成功!",
"ancientBooksInfo": [ { "section": "学而篇", "...": "..." } ],
"maxResult": 20,
"allNum": 20,
"allPages": 1,
"currentPage": 1
}
}
```
## 进阶 / 边界
- **每页 20 条是默认**:如需调整页大小,可尝试传 `maxResult`(参数是否开放以接口实际返回为准;本系列不编造未文档化参数,建议以 `allPages` 为翻页依据)。
- **以 `allPages` 为终止条件最稳**:不要自己算页数,直接 `while currentPage < allPages` 翻页,避免漏页或越界。
- **请求频率**:免费接口设使用档次限制,翻页循环请控制节奏,避免触发限流(详见[常见问题与避坑](https://www.showapi.com/guides/ancient-books-faq-1643))。
- **缓存整本书**:同一 `titleId` 的内容稳定,抓全后可本地缓存,减少重复调用。
## FAQ
**Q1:page 从 0 还是 1 开始?**
A:从 1 开始(实测 `page=1` 返回第一页)。不传默认第 1 页。
**Q2:怎么知道翻完了?**
A:比较 `currentPage` 与 `allPages`,相等即最后一页。
**Q3:allNum 和 allPages 什么关系?**
A:`allPages = ceil(allNum / maxResult)`(实测《论语》allNum=20、maxResult=20、allPages=1)。
## 相关能力 / 下一步阅读
- [古籍查询 API 返回字段全解:trainslation 拼写坑与每个字段含义](https://www.showapi.com/guides/ancient-books-fields-1643)
- [古籍查询 API:按 titleId 获取古籍明细(原文 / 译文 / 注释)](https://www.showapi.com/guides/ancient-books-detail-1643)
- [古籍查询 API 常见问题与避坑指南(trainslation 拼写、注释为空、分页)](https://www.showapi.com/guides/ancient-books-faq-1643)
- **本系列共 10 篇**:查看[古籍查询 API 指南总目录](https://www.showapi.com/guides/ancient-books-guides-1643)