技术博客
易源合一快速接入:用 curl 把「昆明今天天气」变成结构化数据

易源合一快速接入:用 curl 把「昆明今天天气」变成结构化数据

作者: 万维易源
2026-09-15
易源合一快速接入curl示例Python示例自然语言API
# 易源合一快速接入:用 curl 把「昆明今天天气」变成结构化数据 > 接入点:3054-1 智能对话(同步) | 请求方式:POST(application/x-www-form-urlencoded) | 返回格式:JSON | 计费:5.5 厘/次,失败不扣费 | 适用人群:第一次接易源合一的开发者 | 最后实测核对:2026-09-15 ## 核心要点 - 一个端点 `https://route.showapi.com/3054-1?appKey=YOUR_APPKEY` 收一句话,同时返回「识别出的意图」「已整理好的答复文本」「底层接口的原始数据」。 - 请求体只有一个必填字段 `text`,AppKey 放在 URL 的 query 里。 - 实测一次调用约 1.2~2.3 秒返回,计费 5.5 厘;未识别的意图返回 `ret_code: -1` 且不扣费。 ## 为什么值得先看一眼 你要做一个能查天气、查快递、看新闻的对话入口。按常规做法,天气接一个接口,快递接一个,新闻再接一个,每个都要写适配、做字段映射、兜异常。 showapi 易源合一接口(apiCode=3054)把这一步收成了一次调用。你只把用户原话丢进去,它自己判断「这句话想干什么」,再调对应能力,把结果整理成一段可以直接念给用户的话。 代价是一句话换一次 5.5 厘的调用。真实收益是省掉 N 个适配层和 N 套字段映射,这个账等你看到后面的返回结构会更好算。 ## 前置条件与接口速览 你需要一个 showapi 账号并在控制台拿到 AppKey。计费有两种方式:买本接口的专用资源包,或者用通用资源包(按接入点单价扣费)。测试阶段两种都能跑。 | 项目 | 值 | |------|-----| | 接口地址 | `https://route.showapi.com/3054-1?appKey={your_appKey}` | | 请求方式 | POST,`content-type: application/x-www-form-urlencoded` | | 请求参数 | `text`(String,必填,意图内容);`args_list`(List,可选,图片的 URL 或 base64) | | 鉴权 | `appKey` 位于 query | | 计费 | 5.5 厘/次,调用成功才计费 | | 并发 | 10 次/秒 | | 返回格式 | JSON,业务数据在 `showapi_res_body` 内 | | 集成能力 | MCP 服务、OpenAPI 3.0 文档、在线调试 | ## 三步跑通第一条请求 ### 第一步:拿到 AppKey 在 showapi 控制台的「我的 AppKey」里拿。下文所有代码里的 `YOUR_APPKEY` 换成它就能直接运行。 ### 第二步:用 curl 发一条 ```bash curl -X POST "https://route.showapi.com/3054-1?appKey=YOUR_APPKEY" \ -H "content-type: application/x-www-form-urlencoded" \ --data-urlencode "text=帮我查找一下昆明今天的天气" ``` `--data-urlencode` 会自动做 URL 编码,中文不用你自己转。如果你手工拼 form 字符串,记得用 UTF-8 编码(`昆明` → `%E6%98%86%E6%98%8E`),用别的编码拼出来的请求体会被网关拒掉。 ### 第三步:换成 Python 或 Node ```python import requests APP_KEY = "YOUR_APPKEY" url = f"https://route.showapi.com/3054-1?appKey={APP_KEY}" resp = requests.post( url, data={"text": "帮我查找一下昆明今天的天气"}, headers={"content-type": "application/x-www-form-urlencoded"}, timeout=20, # 文档标注接入点读超时 60s,客户端建议 20s 兜底 ) resp.raise_for_status() data = resp.json() if data.get("showapi_res_code") != 0: raise RuntimeError(f"通道异常: {data.get('showapi_res_error')}") body = data.get("showapi_res_body", {}) if body.get("ret_code") != 0: # 未识别的意图走这里,ret_msg 是给人看的原因 print("没听懂:", body.get("ret_msg"), "本次不扣费:", data.get("showapi_fee_num") == 0) else: print("意图:", body["intent"]["name"], body["intent"]["args"]) print("答复:", body["reply_msg"]["text"]) print("原始数据:", body["result"][0]) ``` ```javascript const APP_KEY = "YOUR_APPKEY"; async function ask(text) { const ctl = new AbortController(); const timer = setTimeout(() => ctl.abort(), 20000); const res = await fetch(`https://route.showapi.com/3054-1?appKey=${APP_KEY}`, { method: "POST", headers: { "content-type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ text }), signal: ctl.signal, }); clearTimeout(timer); if (!res.ok) throw new Error(`HTTP ${res.status}`); const data = await res.json(); const body = data.showapi_res_body || {}; if (body.ret_code !== 0) return { ok: false, reason: body.ret_msg }; return { ok: true, intent: body.intent.name, text: body.reply_msg.text, raw: body.result }; } ask("帮我查找一下昆明今天的天气").then(console.log); ``` ## 真实返回长什么样 下面这段是 2026-09-15 用 `帮我查找一下昆明今天的天气` 打出来的真实返回,只删了 `result[0].dayList` 里的重复项: ```json { "showapi_res_error": "", "showapi_res_code": 0, "showapi_fee_num": 1, "showapi_res_body": { "reply_msg": { "img_list": [], "audio_list": [], "text": "#### 昆明 26年09月15日的天气\n\n预计白天气温:24℃,多云,南风0-3级,夜间气温:17℃,多云,东风0-3级。\n\n", "video_list": [] }, "ret_code": 0, "result": [ { "area": "昆明", "areaid": "101290101", "areaCode": "530100", "dayList": [ { "daytime": "20260915", "day_weather": "多云", "day_weather_code": "01", "day_air_temperature": "24", "day_wind_direction": "南风", "day_wind_power": "0-3级", "night_weather": "多云", "night_weather_code": "01", "night_air_temperature": "17", "night_wind_direction": "东风", "night_wind_power": "0-3级", "day_weather_pic": "https://app1.showapi.com/weather/icon/day/01.png" } ] } ], "intent": { "name": "weather", "args": { "area": "昆明", "date": "2026-09-15" } } } } ``` 三块内容的用途不一样: | 字段 | 你怎么用 | |------|---------| | `reply_msg.text` | 直接展示给用户。**实测是 Markdown**(`#### ` 标题、`\n\n` 分段),前端要按 Markdown 渲染,别当纯文本塞进 `<p>` | | `intent.name` / `intent.args` | 自己写业务分支时用。`weather` 表示天气意图,`args.date` 实测返回标准化日期 `2026-09-15`,不是「今天」这类相对词 | | `result` | 要自己画卡片、做二次加工时用。**结构随意图变化**,天气给气象原始字段,快递给快递业务字段,新闻给分页对象 | `result` 的结构差异比想象中大,专门写了一篇拆解 → [易源合一返回三层结构:reply_msg / intent / result 逐层拆解](https://www.showapi.com/guides/united-api-response-structure-3054)。 ## 三个必须提前知道的边界 **第一,`result` 不是固定结构。** 别写 `result[0].dayList` 这种硬编码解析,先按 `intent.name` 分流。 **第二,`confidence` 实测是 0~100 的整数。** 官方文档的返回示例里写的是 `0.99572587013245`,实测同一批调用拿到的都是 100、98、95 这样的整数(2026-09-15)。你的阈值按整数写。 **第三,短句和寒暄类输入识别不稳定。** 对同一句话「你好」连续调用 6 次(3054-1),实测拿到 4 种不同结果:2 次命中 `joke` 成功、1 次命中 `query_news` 成功、2 次返回 `ret_code: -1` + `must input content field`、1 次返回 `调用失败:推理失败3`。业务价值明确的句子则稳定,同一时段「讲个笑话」6/6 命中 `joke`,「帮我查找一下昆明今天的天气」6/6 命中 `weather`。低信息量的输入不要把结果当确定值用。 ## FAQ **Q1:易源合一返回 `ret_code: -1` 是什么意思?** `ret_code: -1` 表示这次没识别成功或执行失败,具体原因看同级的 `ret_msg`。实测遇到过三种文案:`抱歉,您的问题我还没有学会,请等待我的更新和完善1`、`must input content field`、`调用失败:推理失败3`。这种情况 `showapi_fee_num` 为 0,不扣费。 **Q2:AppKey 放在请求头可以吗?** 本接口的 OpenAPI 文档声明的鉴权位置是 query(`apiKey in query, name=appKey`),按 query 传最稳。请求体里只需要放 `text` 和可选的 `args_list`。 **Q3:为什么返回的天气和手机天气 App 不完全一致?** `reply_msg.text` 的温度、风力来自底层气象数据源,实测 2026-09-15 昆明白天 24℃ / 夜间 17℃,和你所在位置、数据的更新时间点都有关系。做展示时把更新时间一并放出来更稳妥。 **Q4:接口有免费额度吗?** 计费按接入点单价 5.5 厘/次计算,调用成功才计费。当前档位与资源包的对应关系以官方产品价格页为准,页面会给出每个规格的可调用次数。 **Q5:一次能问多个问题吗?** `text` 是一句话,实测按单句做意图识别,没有多轮上下文。要串联多步,得在你自己那侧维护会话状态。 ## 下一步阅读 - [易源合一实测能识别哪些意图:8 类 intent 编码逐一验证](https://www.showapi.com/guides/united-api-intent-list-3054) - [易源合一返回三层结构:reply_msg / intent / result 逐层拆解](https://www.showapi.com/guides/united-api-response-structure-3054) - [易源合一调用失败扣不扣费:ret_code 与 showapi_fee_num 实测对照表](https://www.showapi.com/guides/united-api-retcode-fee-3054) - **本系列共 12 篇**:查看[易源合一指南总目录](https://www.showapi.com/guides/united-api-guides-3054)