技术博客
唐诗宋词元曲查询:免费也有档次限制,如何用本地缓存避免触发限流?

唐诗宋词元曲查询:免费也有档次限制,如何用本地缓存避免触发限流?

作者: 万维易源
2026-09-03
唐诗宋词元曲查询免费限流本地缓存Redis
# 唐诗宋词元曲查询:免费也有档次限制,如何用本地缓存避免触发限流? > 接口:唐诗宋词元曲等诗词查询(apiCode=1620)· 免费(有使用档次限制)· 请求方式 POST/GET · 返回 JSON · 适用:已接入、担心触发限流的开发者 · 阅读约 6 分钟 ## 核心要点 - 接口**免费但设有使用档次(积分)限制**以防滥用,高频/重复调用会消耗档位、可能触发限流 - 诗词类数据相对稳定,最适合做本地缓存:朝代列表几乎不变,诗人/诗词可按 ID 做键缓存 - 缓存核心是「以 ID 为键、设置合理 TTL、命中即返回」,可显著降低真实调用次数(具体节省比例取决于你的访问模式,需实测) ## Why:免费不等于能随意刷 很多团队一看「免费」就放心高频调用,结果没几天发现请求被限。文档明确写着「为防止滥用设有使用档次限制」。诗词数据本身变化极慢(朝代、诗人、古诗都是相对稳定的),绝大多数请求其实是重复查询。把结果缓存在自己这边,既保护自己不被限流,也提升响应速度——这是接入免费接口的基本功。 ## What:限流与缓存前提 | 项目 | 说明 | |------|------| | 计费 | 免费,注册默认可调用,有使用档次(积分)限制 | | 档位说明 | 以官方免费 API 页面为准,文档未给具体数字 | | 限流表现 | 文档未公开具体限流码;超档位时可能出现调用受限,需以 `remark` 提示为准 | | 数据稳定性 | 朝代列表极稳定;诗人/诗词更新频率低,适合缓存 | ## How:三层缓存实践 ### 步骤 1 · 设计缓存键 以接口 + 入参特征做键,例如: - 1620-3 朝代列表:`poem:dynasties`(全局一份) - 1620-4 诗人:`poem:poet:{dynastyId或poet}` 或 `poem:poet:id:{poetId}` - 1620-5 诗词:`poem:poems:poet:{poetId}:page:{page}` 或 `poem:poem:id:{poemId}` ### 步骤 2 · 先查缓存,未命中再调接口 **Python(requests + 内存缓存示意,生产可换 Redis)** ```python import requests, time APP_KEY = "YOUR_APPKEY" H = {"content-type": "application/x-www-form-urlencoded"} CACHE = {} # 生产环境换成 Redis:redis.get / redis.setex def cached_call(path, key, ttl=86400, **params): if key in CACHE and CACHE[key][1] > time.time(): return CACHE[key][0] # 命中缓存 r = requests.post(f"https://route.showapi.com/{path}", params={"appKey": APP_KEY, **params}, headers=H, timeout=10) body = r.json().get("showapi_res_body", {}) if body.get("ret_code") != "0": raise RuntimeError(body.get("remark")) CACHE[key] = (body, time.time() + ttl) # 写入缓存,TTL 1 天 return body # 朝代列表几乎不变,长 TTL dyn = cached_call("1620-3", "poem:dynasties", ttl=7*86400) # 某诗人作品,按 poetId+page 缓存 poems = cached_call("1620-5", "poem:poems:poet:5b1e3644cbf69480cb8e81b7:page:1", poetId="5b1e3644cbf69480cb8e81b7", page=1) ``` **Redis 版关键片段(伪代码)** ```python import redis r = redis.Redis(host="localhost", port=6379, db=0) def cached_call_redis(path, key, ttl, **params): hit = r.get(key) if hit: return json.loads(hit) # 命中 body = real_call(path, **params) r.setex(key, ttl, json.dumps(body)) # 写回,TTL 秒 return body ``` **Node.js(fetch + Map 缓存示意)** ```javascript const APP_KEY = "YOUR_APPKEY"; const H = { "content-type": "application/x-www-form-urlencoded" }; const cache = new Map(); async function cachedCall(path, key, ttl, params) { const hit = cache.get(key); if (hit && hit.exp > Date.now()) return hit.data; const resp = await fetch(`https://route.showapi.com/${path}?appKey=${APP_KEY}`, { method: "POST", headers: H, body: new URLSearchParams(params), }); const body = (await resp.json()).showapi_res_body; if (body.ret_code !== "0") throw new Error(body.remark); cache.set(key, { data: body, exp: Date.now() + ttl * 1000 }); return body; } ``` ### 步骤 3 · 设置差异化 TTL - 朝代列表:7 天(几乎不变) - 诗人 `biography`:1~7 天 - 诗词 `contentlist`:1~3 天(低频更新) - 翻页拉全量结果:缓存整份,避免重复翻 13 页 ## 返回示例与解析 缓存前后的调用次数对比(逻辑示意,非文档数字): ``` 无缓存:每次访问苏轼页 → 调 1620-5 × N 次/天 加缓存:首次调 1 次写入,之后 N 次均命中本地 → 真实调用 ≈ 1 次/天 ``` > 具体节省比例取决于你的访问分布(热点集中度、是否翻全量),**需结合自身流量实测**,本文不给出固定百分比。 ## 进阶 / 边界 - **先缓存、后限流**:缓存能挡掉绝大多数重复请求,是比「限流算法」更优先的手段。 - **TTL 不是越长越好**:诗词极少变,但数据源仍可能修订译文/注释,设 1~7 天 TTL 并支持手动刷新即可。 - **缓存键要含全部入参**:1620-5 的 `poetId`+`page` 都要进键,否则不同页会串数据。 - **档位未知要先评估**:文档未给具体档位数字,上线前建议用小流量探明实际限额,再定 TTL 与缓存命中率目标。 ## FAQ **Q1:免费接口也会被限流吗?** 会。文档写明「为防止滥用设有使用档次限制」,超出档位可能被限制调用。具体限额以官方免费 API 页面为准。 **Q2:缓存能完全避免限流吗?** 缓存能消除重复查询,大幅降低调用量,但是首次冷启动、缓存过期后的回源请求仍会计入档位。配合合理 TTL 与预热(热门诗人提前缓存)效果最佳。 **Q3:可以用 CDN/浏览器缓存吗?** `appKey` 在 URL 中,浏览器侧缓存会把密钥与响应一起缓存、且有跨用户串数据风险,不建议。缓存应放在你自己的服务端(Redis/内存)。 **Q4:文档没给限流错误码,怎么判断被限流了?** 文档未公开具体限流码。若返回异常或 `remark` 提示受限,先暂停并以指数退避重试;同时检查是否因未缓存导致请求过量。 ## 相关能力 / 下一步阅读 - [唐诗宋词元曲查询:page 与 maxResult=20 分页翻页拉取全部诗词](https://www.showapi.com/guides/poem-pagination-1620) — 翻页拉全量时务必配合缓存 - [唐诗宋词元曲查询返回结构全解:ret_code、dynastyInfo、poemInfo 一文读懂](https://www.showapi.com/guides/poem-response-fields-1620) — 字段与判断依据 - **本系列共 12 篇**:查看[唐诗宋词元曲查询指南总目录](https://www.showapi.com/guides/poem-guides-1620)