唐诗宋词元曲查询:原文/译文/注释三件套结构解读与前端排版建议
唐诗宋词元曲查询contentlist原文译文注释前端排版 # 唐诗宋词元曲查询:原文/译文/注释三件套结构解读与前端排版建议
> 接口:唐诗宋词元曲等诗词查询(apiCode=1620)· 接入点 1620-5 · 免费 · 返回 JSON · 适用:前端开发者、内容排版同学 · 阅读约 6 分钟
## 核心要点
- 诗词正文在 `poemInfo[].contentlist` 中,它是**数组**:一首诗可能分多段,每段含 `original`(原文)、`translation`(译文)、`annotation`(注释)
- 原文自带生僻字注音,形如「壬(rén)戌(xū)」,可直接展示或拆出拼音做悬浮提示
- `note` 字段是标签串(如「辞赋精选,高中文言文…」),可作为学段/主题筛选依据
## Why:排版翻车,多半是没吃透 contentlist 结构
开发者常把 `contentlist` 当单对象,直接取 `contentlist.original` 结果取到 `undefined`;或忽略多段,只显示了辞赋的第一段。本篇把 `contentlist` 的数组结构、注音格式、标签用法讲透,并给出版式建议,照做即可稳定渲染。
## What:字段与结构速览
| 项目 | 说明 |
|------|------|
| 接入点 | 1620-5 名称查询诗词列表 |
| 主体数组 | `poemInfo`(诗列表)→ 每首诗的 `contentlist`(段落列表) |
| 段落字段 | `original` / `translation` / `annotation` |
| 辅助字段 | `note`(标签串)、`title` / `poet` / `dynasty` |
| 返回格式 | JSON,业务数据在 `showapi_res_body` |
**结构示意**
```
poemInfo[] // 诗列表(数组)
└─ contentlist[] // 段落列表(数组,可多段)
├─ original // 原文(含注音)
├─ translation // 译文
└─ annotation // 注释
```
## How:稳健解析与排版
### 步骤 1 · 两层遍历取数据
**Python(requests)**
```python
import requests
APP_KEY = "YOUR_APPKEY"
H = {"content-type": "application/x-www-form-urlencoded"}
r = requests.post("https://route.showapi.com/1620-5",
params={"appKey": APP_KEY, "title": "前赤壁赋", "page": 1},
headers=H, timeout=10)
body = r.json().get("showapi_res_body", {})
if body.get("ret_code") != "0":
raise RuntimeError(body.get("remark"))
for poem in body["poemInfo"]: # 诗列表
print(poem["title"], poem["poet"], poem["dynasty"])
print("标签:", poem.get("note"))
for seg in poem["contentlist"]: # 段落列表
print("【原文】", seg["original"])
print("【译文】", seg["translation"])
print("【注释】", seg["annotation"])
```
**cURL**
```bash
curl -X POST "https://route.showapi.com/1620-5?appKey=YOUR_APPKEY" \
-H "content-type: application/x-www-form-urlencoded" \
-d "title=%E5%89%8D%E8%B5%A4%E5%A3%81%E8%B5%8B&page=1"
```
**Node.js(fetch)**
```javascript
const APP_KEY = "YOUR_APPKEY";
const body = (await (await fetch(`https://route.showapi.com/1620-5?appKey=${APP_KEY}`, {
method: "POST", headers: { "content-type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({ title: "前赤壁赋", page: 1 }),
})).json()).showapi_res_body;
body.poemInfo.forEach(p => p.contentlist.forEach(s => {
console.log("原文", s.original, "| 译文", s.translation);
}));
```
### 步骤 2 · 注音处理(可选)
原文中注音格式为「字(拼音)」,可用正则拆出:
```javascript
// 把「壬(rén)戌(xū)」拆成 {char:"壬", py:"rén"}
const m = original.match(/([\u4e00-\u9fa5])\(([^)]+)\)/g) || [];
```
可渲染为「壬」字上悬浮显示「rén」,或直接原样展示。
### 步骤 3 · 版式建议
- **逐段对照**:原文、译文、注释三段并列或上下对照;长辞赋按 `contentlist` 分段展示,每段可独立收起注释。
- **标签展示**:`note` 拆成逗号分隔的标签,作为难度/主题 chips(如「高中文言文」「古文观止」)。
- **空值兜底**:`translation` / `annotation` 可能为空,展示前判空,避免「undefined」。
## 返回示例与解析
```json
{
"showapi_res_body": {
"ret_code": "0",
"poemInfo": [
{
"title": "前赤壁赋",
"dynasty": "宋代",
"poet": "苏轼",
"note": "辞赋精选,高中文言文,古文观止,写景,饮酒,感叹,哲理",
"contentlist": [
{
"original": "壬(rén)戌(xū)之秋,七月既望……",
"translation": "壬戌年秋,七月十六日……",
"annotation": "壬戌:宋神宗元丰五年……"
}
]
}
]
}
}
```
| 字段 | 排版用途 |
|------|---------|
| `original` | 主展示,含注音,可加大字号 |
| `translation` | 对照展示,灰色辅助 |
| `annotation` | 折叠/悬浮展示,按需展开 |
| `note` | 拆分为标签 chips,标识学段与主题 |
## 进阶 / 边界
- **多段是常态**:辞赋/长诗会拆成多个 `contentlist` 元素,每段独立原文/译文/注释,务必遍历,不要只取 `[0]`。
- **注音非标准拼音方案**:注音嵌在原文文本内(「字(拼音)」),不是独立字段;要做拼音高亮需自己解析,注意有些字可能无注音。
- **注释可能很长**:`annotation` 是连续文本,可截断+「展开全文」,避免撑爆卡片。
- **译文仅供参考**:数据源提供的译文/注释为辅助学习材料,正式发布前建议人工校对。
## FAQ
**Q1:contentlist 一定是数组吗?能不能当对象直接用?**
是数组。即使一首诗只有一段,它也是长度为 1 的数组。请用 `for`/下标遍历,不要写 `poem.contentlist.original`(会 undefined)。
**Q2:为什么我只看到第一段,后面没了?**
你大概率只取了 `contentlist[0]`。长文被分成多段,需遍历全部元素;前端也可加「加载更多段落」。
**Q3:注音能不能单独抽出来做拼音标注?**
可以。注音以「字(拼音)」形式内嵌在 `original` 中,用正则提取即可;但属于自行解析,需处理个别无注音字。
**Q4:note 标签能用来做检索或分类吗?**
`note` 是返回字段,不是查询参数,不能用于接口检索;但返回后可在本地按逗号拆分做标签筛选/展示。
## 相关能力 / 下一步阅读
- [唐诗宋词元曲查询:搭一个带原文/译文/注释的古诗文学习卡片](https://www.showapi.com/guides/poem-learning-card-1620) — 用 contentlist 做学习卡片
- [唐诗宋词元曲查询返回结构全解:ret_code、dynastyInfo、poemInfo 一文读懂](https://www.showapi.com/guides/poem-response-fields-1620) — 全字段速查
- **本系列共 12 篇**:查看[唐诗宋词元曲查询指南总目录](https://www.showapi.com/guides/poem-guides-1620)