# 常见疾病查询:5 分钟从注册到拿到第一篇疾病明细
> 接口:常见疾病查询(apiCode=546)· 免费 · 请求方式 POST/GET · 返回格式 JSON · 适用人群:新注册用户、初级开发者 · 阅读时间:约 5 分钟
## 核心要点
- 常见疾病查询是**免费官方自营**接口,含 3 个接入点:科目树(546-1)、关键字检索(546-2)、疾病明细(546-3)。
- 三步链路是「**先查科目树 → 再按关键词检索拿疾病 id → 最后用 id 取明细**」,明细里的 `tagList` 才是症状/诊断/治疗/预防。
- 调用只需一个 `appKey`(放在 query 参数),546-1 无业务参数、546-3 的 `id` 必填,其余参数均可选。
## Why:这跟我有什么关系
如果你在做医院导诊、挂号入口、健康科普或医疗知识库,最常见的一个需求是:「用户输入一个症状或病名,系统告诉他该挂哪个科、这个病是怎么回事」。常见疾病查询把这件事拆成三个免费、同步的接口:
1. **科目树(546-1)**——告诉你医院有哪些科室(一级/二级),是导诊的「地图」。
2. **关键字检索(546-2)**——按病名或关键词搜出疾病列表,每条带一个 `id`。
3. **疾病明细(546-3)**——用 `id` 取详情,里面用 `tagList` 存了症状、诊断、治疗、预防等结构化内容。
跑通这三步,你就拥有了一个最小可用的「症状 → 科室 → 病种知识」闭环,而且**完全免费**。
## What:前置条件与接口速览
| 项 | 说明 |
|----|------|
| 接口 | 常见疾病查询(apiCode=546) |
| 服务商 | 昆明秀派科技有限公司(易源官方自营) |
| 计费 | 免费服务 |
| 请求方式 | POST / GET |
| 返回格式 | JSON |
| 鉴权 | `appKey`(query 参数,从控制台获取) |
| 接入点 | 546-1 查询疾病科目 / 546-2 关键字查询疾病 / 546-3 取得疾病明细 |
| 集成能力 | MCP(`showapi.com.cn/mcp/546/{appKey}`)、OpenAPI 3.0(YAML/JSON) |
前置条件:注册易源账号 → 在[控制台](https://www.showapi.com/console#/myApp)创建应用拿到 `appKey`。
## How:三步跑通(Python / cURL / Node.js)
下面用同一个最小链路演示:取科目树 → 在「内科(typeId=3)」下搜「高血压」→ 用返回的 `id` 取明细。
### Python(requests)
```python
import requests
APP_KEY = "YOUR_APPKEY" # 替换为你的真实 AppKey
BASE = "https://route.showapi.com"
def call(point, **params):
"""统一调用:系统级 showapi_res_code 与业务级 ret_code 双重校验。"""
resp = requests.post(
f"{BASE}/{point}",
params={"appKey": APP_KEY}, # appKey 走 query
data=params, # 业务参数走 form body
headers={"content-type": "application/x-www-form-urlencoded"},
timeout=10,
)
resp.raise_for_status()
data = resp.json()
if data.get("showapi_res_code") != 0: # 系统级失败
raise RuntimeError(f"系统错误: {data.get('showapi_res_error')}")
body = data["showapi_res_body"]
if str(body.get("ret_code")) != "0": # 业务级失败(0=成功,文档仅定义 0/非0)
raise RuntimeError(f"业务失败 ret_code={body.get('ret_code')}")
return body
# ① 科目树(无业务参数)
depts = call("546-1")
print("一级科目数:", len(depts["list"])) # 例:20 个一级科目
# ② 关键字检索:在内科(typeId=3)下搜"高血压"
hits = call("546-2", typeId="3", key="高血压", page="1")
for d in hits.get("contentlist", []):
print(d["id"], d["name"], d.get("typeName"))
# ③ 取得明细:用上一步的疾病 id
if hits.get("contentlist"):
detail = call("546-3", id=hits["contentlist"][0]["id"])
item = detail["item"][0]
print("疾病:", item["name"], "| 别名:", item.get("alias", ""))
for tag in item.get("tagList", []):
print(f" 【{tag['name']}】{tag['content']}")
```
### cURL
```bash
# ① 科目树
curl -X POST "https://route.showapi.com/546-1?appKey=YOUR_APPKEY" \
-H "content-type: application/x-www-form-urlencoded"
# ② 关键字检索(内科 typeId=3,关键词"高血压",第 1 页)
curl -X POST "https://route.showapi.com/546-2?appKey=YOUR_APPKEY" \
-H "content-type: application/x-www-form-urlencoded" \
--data-urlencode "typeId=3" --data-urlencode "key=高血压" --data-urlencode "page=1"
# ③ 取得明细(id 替换为 546-2 返回的真实疾病 id)
curl -X POST "https://route.showapi.com/546-3?appKey=YOUR_APPKEY" \
-H "content-type: application/x-www-form-urlencoded" \
--data-urlencode "id=<疾病id>"
```
### Node.js(fetch)
```javascript
const APP_KEY = "YOUR_APPKEY";
const BASE = "https://route.showapi.com";
async function call(point, params = {}) {
const url = new URL(`${BASE}/${point}`);
url.searchParams.set("appKey", APP_KEY);
const resp = await fetch(url, {
method: "POST",
headers: { "content-type": "application/x-www-form-urlencoded" },
body: new URLSearchParams(params).toString(),
});
const data = await resp.json();
if (data.showapi_res_code !== 0) throw new Error(data.showapi_res_error);
const body = data.showapi_res_body;
if (String(body.ret_code) !== "0") throw new Error(`业务失败 ret_code=${body.ret_code}`);
return body;
}
const depts = await call("546-1");
console.log("一级科目数:", depts.list.length);
```
## 返回示例与解析
546-1 返回(节选):
```json
{
"showapi_res_code": 0,
"showapi_res_body": {
"ret_code": 0,
"list": [
{ "typeName": "内科", "typeId": "3",
"subList": [ { "subName": "呼吸内科", "subId": "0301" } ] }
]
}
}
```
- `showapi_res_code`:系统级状态码,0 为成功。
- `showapi_res_body.ret_code`:业务级状态码,0 为成功;**文档未提供细分错误码**,非 0 即失败,排查看系统级 `showapi_res_error` 或业务返回信息。
- 546-3 明细的 `tagList` 是核心:`[{ "name": "症状", "content": "..." }, { "name": "诊断", ... }, { "name": "治疗", ... }, { "name": "预防", ... }]`。
## 进阶 / 边界
- **546-2 的 `key` 不是必填**:四个参数(typeId/subTypeId/key/page)全部可选,空参调用会返回跨全部分页的疾病列表(每页最多 20 条)。
- **546-3 的 `id` 必填**,且这个 `id` 来自 546-2 的返回,不要自己拼。
- **免费服务稳定性**:免费接口通常对调用频率有限制,生产环境建议对 546-1 科目树做缓存(见[缓存策略](https://www.showapi.com/guides/disease-query-cache-546))。
- **非诊疗免责**:返回内容仅供参考,不能替代医生诊断;在 UI 上务必加「仅供参考,请以医生诊断为准」提示。
## FAQ
**Q1:这个接口真的免费吗?**
A:详情页标注为「免费服务」,调用不按次扣费。具体免费额度/频率限制以官方说明为准。
**Q2:为什么 546-3 返回提示错误?**
A:最常见原因是 `id` 没传或传错。`id` 必须来自 546-2 关键字查询的返回;先调 546-2 拿到 `id` 再调 546-3。
**Q3:546-2 不传关键词能查吗?**
A:能。typeId/subTypeId/key/page 全部可选,空参即返回全量分页列表。
**Q4:返回里的 ret_code 和 showapi_res_code 有什么区别?**
A:`showapi_res_code` 是系统级(鉴权/网关),`ret_code` 是业务级(0=成功)。两者都为 0 才算真正成功。
## 相关能力 / 下一步阅读
- [常见疾病查询返回字段全解:科目树、疾病列表与明细结构一文读懂](https://www.showapi.com/guides/disease-query-response-fields-546)
- [常见疾病查询:科目树 → 关键字 → 明细 三步入诊全链路设计](https://www.showapi.com/guides/disease-query-pipeline-546)
- [常见疾病查询:取得疾病明细并解析症状/诊断/治疗/预防(546-3 的 tagList)](https://www.showapi.com/guides/disease-query-detail-546)
- **本系列共 12 篇**:查看[常见疾病查询指南总目录](https://www.showapi.com/guides/disease-query-guides-546)