# 免费接口下如何设计分页缓存,减少重复调用?
> 接口:成语词典(apiCode=2964) · 接入点:搜索成语(2964-1) · 是否免费:是 · 请求方式:POST/GET · 返回格式:JSON · 适用人群:中高级开发者、架构师 · 阅读时间:约 6 分钟
## 核心要点
- 即便免费,重复调用也浪费延迟、且受频率约束;本地缓存能显著降调用量。
- 搜索结果按 `keyword+page` 缓存;详情按 `id` 缓存(id 稳定不变)。
- 缓存键设计参考:`idiom:search:{keyword}:{page}`、`idiom:detail:{id}`。
## Why:免费也要省
免费服务不等于「随便刷」。高频重复查同一关键词、同一成语,既拖慢响应又可能触发频率限制。合理的缓存能让热门词和常用成语命中本地,调用量下降一个数量级,用户体验也更顺。
## What:可缓存的数据点
| 数据 | 缓存键 | 稳定性 |
|------|--------|--------|
| 搜索某关键词某页 | `idiom:search:{keyword}:{page}` | 成语库更新才变,可较长 TTL |
| 某成语详情 | `idiom:detail:{id}` | id 唯一,长期有效 |
| 随机成语 | 不建议缓存(要的是「随机」) | — |
## How:Redis 缓存实现
```python
import requests, redis, json, hashlib
APPKEY = "YOUR_APPKEY"
rds = redis.Redis(host="localhost", port=6379, db=0)
def search_cached(keyword, page=1, ttl=86400):
key = f"idiom:search:{keyword}:{page}"
hit = rds.get(key)
if hit:
return json.loads(hit)
resp = requests.get("https://route.showapi.com/2964-1",
params={"appKey": APPKEY, "keyword": keyword, "page": str(page)},
timeout=10).json()["showapi_res_body"]
rds.setex(key, ttl, json.dumps(resp, ensure_ascii=False))
return resp
def detail_cached(id_, ttl=86400*7):
key = f"idiom:detail:{id_}"
hit = rds.get(key)
if hit:
return json.loads(hit)
resp = requests.post("https://route.showapi.com/2964-2",
data={"appKey": APPKEY, "id": id_}, timeout=10).json()["showapi_res_body"]
rds.setex(key, ttl, json.dumps(resp, ensure_ascii=False))
return resp
```
### 翻页去重(避免重复拉同一页)
用 `allPages` 控制循环上限,已缓存页直接跳过:
```python
def search_all_cached(keyword):
out, page = [], 1
while True:
b = search_cached(keyword, page) # 命中缓存则不再发请求
out.extend(b["list"])
if page >= b["allPages"]:
break
page += 1
return out
```
## 进阶 / 边界
- **TTL 选择**:搜索列表 TTL 可设 1 天;详情(id 稳定)可设 7 天甚至更长。成语库极少变动,长 TTL 安全。
- **随机成语不要缓存**:用户要的是「每次不同」,缓存会破坏随机性。
- **失效策略**:若需强一致(如成语库有更新),用「版本号前缀」做缓存命名空间,更新时换前缀批量失效。
- **限流兜底**:即便有缓存,突发流量仍建议加令牌桶([限流参考](https://www.showapi.com/guides/idiom-free-api-cost-2964))。
## FAQ
**Q:免费接口还有必要缓存吗?**
有必要。降延迟、防频率限制、省钱(若未来转付费按次计费更是直接省)。
**Q:缓存键用什么最稳?**
搜索用 `keyword+page`,详情用 `id`(id 唯一且不变)。
**Q:缓存会拿到过期释义吗?**
成语释义极少变动,长 TTL 风险低;若要求强一致,用命名空间版本号失效。
**Q:随机成语能缓存吗?**
不建议,会破坏「每次随机」的语义。
## 相关能力 / 下一步阅读
- [成语搜索关键词怎么写才准?部分匹配 / 分页技巧](https://www.showapi.com/guides/idiom-search-keyword-tips-2964)
- [成语词典是免费服务意味着什么?showapi_fee_num 与配额说明](https://www.showapi.com/guides/idiom-free-api-cost-2964)
- [成语词典返回字段全解:showapi_res_body 与 ret_code 一文读懂](https://www.showapi.com/guides/idiom-dictionary-response-codes-2964)
- **本系列共 15 篇**:查看[成语词典(apiCode=2964)官方指南总目录](https://www.showapi.com/guides/idiom-dictionary-guides-2964)