中文分词接口:免费档位下的限流与调用策略
chinese-segmentation-free-tier-269 # 中文分词接口:免费档位下的限流与调用策略
> 接口:中文分词接口(269-1) · 免费 · POST/GET · JSON · 适用人群:已接入用户、后端 · 阅读时间:8 分钟
## 核心要点
- 本接口为免费服务,注册即默认可调用,但设有使用档位限制(具体额度以[官方档位说明](https://www.showapi.com/free-api)为准)。
- 免费额度下更要"省着用":相同文本加缓存、客户端令牌桶限流、失败指数退避重试。
- 这三招直接减少无效调用,让免费档位更经用、线上更稳。
## Why:免费≠可以随便打
免费接口降低了试错成本,但档位限制意味着无限高频会触发限流,反而影响业务。合理的限流 + 缓存,既守住免费额度,又保证高峰期不雪崩。这是接入生产前必做的一步。
## What:策略速览
| 策略 | 作用 | 做法 |
|------|------|------|
| 结果缓存 | 相同文本不重复调用 | 以 `text` 哈希为 key,存 `list` |
| 客户端限流 | 不超免费档位速率 | 令牌桶 / 漏桶 |
| 失败重试 | 瞬时失败自愈 | 指数退避,限定次数 |
## How:缓存 + 限流 + 重试
**Python(Redis 缓存 + 令牌桶 + 退避)**
```python
import urllib.request, urllib.parse, json, time, hashlib, threading
APP_KEY = "YOUR_APPKEY"
_sem = threading.Semaphore(8) # 并发上限,按免费档位调
cache = {} # 生产环境换成 Redis
def _call(text):
url = f"https://route.showapi.com/269-1?appKey={APP_KEY}"
data = urllib.parse.urlencode({"text": text}).encode("utf-8")
req = urllib.request.Request(url, data=data,
headers={"content-type": "application/x-www-form-urlencoded"})
with urllib.request.urlopen(req, timeout=10) as resp:
res = json.loads(resp.read().decode("utf-8"))
body = res.get("showapi_res_body", {})
if body.get("ret_code") != 0:
raise RuntimeError(f"ret_code={body.get('ret_code')}")
return body.get("list", [])
def segment(text, retries=3):
key = hashlib.md5(text.encode("utf-8")).hexdigest()
if key in cache:
return cache[key] # 命中缓存,免调用
with _sem:
delay = 0.5
for attempt in range(retries):
try:
words = _call(text)
cache[key] = words
return words
except Exception as e:
if attempt == retries - 1:
raise
time.sleep(delay) # 指数退避
delay *= 2
return []
```
**cURL(单次,配合脚本循环时自行限速)**
```bash
curl -X POST "https://route.showapi.com/269-1?appKey=YOUR_APPKEY" \
--data-urlencode "text=需要分词的文本"
```
**Node.js(简单令牌桶)**
```js
const sem = new (require("semaphore")(8)); // npm i semaphore,或自实现
async function segmentCached(text, cache = new Map()) {
const key = require("crypto").createHash("md5").update(text).digest("hex");
if (cache.has(key)) return cache.get(key);
await new Promise(r => sem.take(r));
try {
const res = await fetch(`https://route.showapi.com/269-1?appKey=YOUR_APPKEY`, {
method: "POST",
headers: { "content-type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({ text }).toString()
}).then(r => r.json());
const list = (res.showapi_res_body || {}).list || [];
cache.set(key, list);
return list;
} finally { sem.leave(); }
}
```
## 返回示例与解析
首次调用写入缓存;相同 `text` 再次请求直接读缓存返回 `list`,不消耗免费额度。限流与退避保证突发流量不击穿档位。
## 进阶 / 边界
- 缓存 key 用 `text` 的哈希;注意 `text` 含前后空格/全半角差异会视为不同 key,必要时先归一化。
- 并发数与限速需对照[免费档位说明](https://www.showapi.com/free-api)设置,本文不罗列具体额度数字。
- 长文本批量场景结合[长文本切分与批量处理](https://www.showapi.com/guides/chinese-segmentation-long-text-269)的切片策略。
## FAQ
**Q:免费额度具体是多少?**
A:以[官方档位说明](https://www.showapi.com/free-api)为准,本文不引用未公开的具体数字。
**Q:缓存会不会返回过期结果?**
A:分词结果对固定文本是确定性的,可放心缓存;若接口升级导致分词变化,按 key 失效策略刷新即可。
**Q:限流触发后返回什么?**
A:以接口实际返回为准(可能为网关层错误);代码应判 `showapi_res_code` 非 0 或异常后走退避重试。
**Q:缓存放内存还是 Redis?**
A:单机原型用内存字典即可;多实例/生产用 Redis 共享,避免各实例重复调用。
## 相关能力 / 下一步阅读
- [中文分词接口:长文本如何切分与批量处理](https://www.showapi.com/guides/chinese-segmentation-long-text-269)
- [中文分词接口:5 分钟从注册到拿到第一条分词结果](https://www.showapi.com/guides/chinese-segmentation-quickstart-269)
- [中文分词接口:中文编码与英文/数字/标点的处理边界](https://www.showapi.com/guides/chinese-segmentation-encoding-269)
- **本系列共 11 篇**:查看[中文分词接口指南总目录](https://www.showapi.com/guides/chinese-segmentation-guides-269)