k-skill highway-traffic-status:基于韩国公开交通 API 的高速路实时拥堵与 CCTV 元数据查询
【免费下载链接】k-skill한국인을 위한 스킬 모음집 - 에이전트를 한국인으로项目地址: https://gitcode.com/GitHub_Trending/ks/k-skill
highway-traffic-status是 k-skill 技能集中的一个纯标准库(stdlib only)Python 查询工具,通过韩国道路公社(data.ex.co.kr)与国立交通信息中心 ITS(openapi.its.go.kr)两个公开 API,实时获取全国高速路区间(콘존/Conzone)级别的通行速度、交通量、拥堵等级,以及坐标范围内的 CCTV 流媒体元数据。读完本文,你将掌握该技能的完整 CLI 用法、全部输入参数与取值范围、响应字段的映射规则,以及源码层面的密钥解析、坐标校验与失败处理机制,可以直接在自己的 Agent 工作流中复用这套「公开 API 直连 + BYOK 兜底」的集成模式。
功能定位与数据源
该技能是**查询专用(조회 전용)**的:不提供路径规划、导航、通行费计算,也不覆盖市内道路(v1 以高速路为中心)。典型适用场景包括「现在京釜高速堵不堵」「首尔收费所附近的拥堵状况」「西海线上行路况如何」「盘谷附近的高速路 CCTV」。
技能对接两个上游公开接口(定义见 highway-traffic-status/scripts/highway_traffic.py):
| 用途 | 端点 | 说明 |
|---|---|---|
| 实时交通量/通行状况 | GET https://data.ex.co.kr/openapi/odtraffic/trafficAmountByRealtime?key=<key>&type=json | 返回全国 VDS 实时快照,按区间提供速度/交通量/等级 |
| CCTV 元数据 | GET https://openapi.its.go.kr:9443/cctvInfo?apiKey=<key>&type=ex&cctvType=1&minX=..&maxX=..&minY=..&maxY=..&getType=json | 按经纬度 bounding box 返回高速路 CCTV 的名称、坐标与流地址 |
两个表面均使用公开演示密钥test即可免注册调用(仓库文档标注于 2026-07-21 验证,见 docs/features/highway-traffic-status.md)。正因为是公开端点,该技能按「免费 API 直连」策略不经过 k-skill-proxy 中转,直接调用上游;当演示密钥被回收或配额不足时,可签发个人密钥并通过环境变量KSKILL_EXDATA_API_KEY/KSKILL_ITS_API_KEY(或~/.config/k-skill/secrets.env中的同名键)覆盖,密钥的格式约定可参考 examples/secrets.env.example。
CLI 使用方式
技能通过 k-skill CLI 以npx -y @nomadamas/k-skill@0 exec <skill> <script> --的形态执行 Python 脚本,运行前提为 Python 3.9+ 且无外部依赖。以下示例完整继承自官方文档:
# 京釜线通行状况摘要(人类可读输出) npx -y @nomadamas/k-skill@0 exec highway-traffic-status scripts/highway_traffic.py -- traffic --route 경부 --text # 仅首尔TG区间,输出结构化 JSON(最多 10 行) npx -y @nomadamas/k-skill@0 exec highway-traffic-status scripts/highway_traffic.py -- traffic --keyword 서울 --limit 10 # 盘谷附近的 CCTV npx -y @nomadamas/k-skill@0 exec highway-traffic-status scripts/highway_traffic.py -- cctv \ --min-x 126.9 --max-x 127.2 --min-y 37.3 --max-y 37.6 --text不追加--text时,两个子命令都输出结构化的 JSON(traffic 为result/total_matched/rows/source,cctv 为result/cameras/source),便于 Agent 进一步解析。
完整参数说明
源码中的 argparse 定义位于 parse_args。全部输入如下表:
| 输入 | 适用子命令 | 说明与限制 |
|---|---|---|
--route | traffic | 线路名的一部分或 4 位线路编号(如경부、0010),客户端侧过滤 |
--keyword | traffic | 区间(콘존)名称关键词(如서울TG、양재),客户端侧过滤 |
--limit | traffic | 输出行数,默认 30 |
--min-x/--max-x | cctv | 经度,须落在 124~132 且 min < max |
--min-y/--max-y | cctv | 纬度,须落在 33~39.5 且 min < max |
--road-type | cctv | ex(默认,高速路)/its(国道)/all |
--text | 两者 | 输出人类可读摘要而非 JSON |
--secrets-path | 两者 | 密钥文件路径,默认~/.config/k-skill/secrets.env |
--timeout | 两者 | 上游请求超时(秒),默认 30 |
CCTV 查询要求四个坐标参数全部提供;当用户只说地名时,需将其换算为大致 bounding box 后再调用(见 instruction.md 的 Workflow 第 2 步)。
源码解析:密钥解析与 URL 构造
密钥优先级。resolve_api_key 的实现是「环境变量优先,secrets 文件兜底」:先取KSKILL_EXDATA_API_KEY(traffic)或KSKILL_ITS_API_KEY(cctv)环境变量,为空时再由 load_secrets 按 dotenv 格式(忽略空行与#注释、剥离引号)读取--secrets-path指向的文件。两者都没有时才回落到源码常量中的演示密钥test(EXDATA_DEMO_KEY/ITS_DEMO_KEY,见 L43-L44)。
URL 构造。build_traffic_url 固定携带key与type=json两个参数;build_cctv_url 则先调用坐标校验,再携带apiKey、type(即--road-type)、cctvType=1、四个坐标与getType=json。
坐标校验前置。_validate_bbox 在发起任何网络请求之前执行:四个坐标缺一即报错;min ≥ max报错;经度须整体落在KOREA_LON_RANGE = (124.0, 132.0)、纬度落在KOREA_LAT_RANGE = (33.0, 39.5)(L48-L49)之内。这样做的目的是在参数明显非法时不浪费上游配额、不触发无意义的远程调用。测试 test_highway_traffic.py 中的test_cctv_bbox_bounds_are_validated与test_cctv_bbox_must_stay_in_korea_range分别覆盖了 min≥max 与越界两种场景。
响应解析:从上游字段到统一模型
traffic 子命令:normalize_traffic 负责把上游 JSON 归一化,映射规则是理解输出的关键:
| 上游字段 | 输出字段 | 转换规则 |
|---|---|---|
grade | congestion | "1"→원활(畅通)、"2"→서행(缓行)、"3"→정체(拥堵),映射表见 L51 |
updownTypeCode | direction | S/N→상행(上行)、E/W→하행(下行) |
speed | speed_kmh | 字符串转整数,非数字时为 null |
trafficAmout | traffic_volume | 注意上游字段名本身是拼写错误(缺少第二个t),源码按原样读取 |
timeAvg | travel_time_sec | 区间平均通行时间(秒) |
stdDate+stdHour | observed_at | 拼成「基准日期 基准时刻」,用于标明快照时点 |
归一化后由 filter_traffic 在客户端完成过滤:--route按「线路名包含关键词,或线路编号精确匹配」命中;--keyword按区间名包含匹配。上游接口只返回全国全量快照,所以过滤完全在本地进行,这也解释了 JSON 输出中total_matched(过滤后总行数)与rows(按--limit截断后实际输出的行)可能不一致。文本模式的渲染见 render_traffic_text,每行形如「[线路 方向] 区间: 拥堵等级 · 速度 · 交通量 (基准时间)」。
cctv 子命令:一个必须知道的「反直觉」细节是——即使请求参数写了getType=json,成功响应实际是XML(这一点在文档、instruction 与源码注释 L19-L20 三处都有强调)。normalize_cctv 的解析策略是双通道:先判断响应体是否以{开头,是则尝试按 JSON 解析为错误信封(header.resultMsg即为错误消息);否则按 XML 解析,遍历<data>节点提取cctvname、cctvurl、cctvformat、coordx/coordy。测试用例 test_normalize_cctv_parses_xml_metadata 与 test_normalize_cctv_raises_on_key_error_json 分别验证了这两条路径。需要注意,返回的url是可能随时失效的签名 HLS 地址,技能本身只提供元数据,不承载流播放;过期后应重新查询刷新。
失败处理与退出码
文档与源码共同约定了一套类型化的失败处理(HelperError统一抛出后写入 stderr 并返回退出码 1,见 run):
| 情形 | 上游表现 | 技能行为 |
|---|---|---|
| exdata 认证密钥错误 | HTTP 200 +{"code":"ERROR","message":"인증키가 유효하지 않습니다."} | 归一化阶段抛出类型化错误,提示申请个人密钥 |
| ITS 认证密钥错误 | HTTP 401 +header.resultCode 4005 | http_get_text 中按 401 或响应体含「인증키」识别,提示个人密钥签发 |
| 空结果 | HTTP 200 但无匹配数据 | 输出result: "empty",退出码仍为 0,建议放宽线路名或坐标范围重试 |
| 坐标范围非法(越界、min≥max) | 不发起请求 | 本地校验直接报错(upstream 未调用) |
| JSON/XML 解析失败、HTTP 错误、超时 | 拦截或维护的可能 | 输出可能性说明后以退出码 1 结束,建议稍后重试 |
其中「HTTP 200 但业务错误」与「HTTP 401」两种密钥失效形态均被单测覆盖:test_normalize_traffic_raises_typed_error_on_upstream_error_code 验证 exdata 的 ERROR 信封,test_run_reports_helper_error_to_stderr 验证错误落到 stderr 且退出码为 1。空结果的显式标记(result: "empty")由 test_run_traffic_empty_result_is_explicit 保证,这使得 Agent 可以程序化地区分「查无数据」与「查询失败」。
边界、约定与演进预留
- 结果呈现约定:通行状态直接采用上游
grade映射(畅通/缓行/拥堵),不叠加主观判断;输出中需带observed_at基准时点,明确其为实时快照(见 instruction.md 的「结果摘要规则」)。 - 安全约定:若用户疑似正在驾驶,应建议语音或同乘者确认,避免行车中操作设备。
- 密钥策略演进:源码 docstring 与 instruction 的 Notes 均说明——当前依赖上游演示密钥
test;一旦密钥政策变化,技能将只能以 BYOK(自带密钥)模式工作,届时会重新评估将其纳入 k-skill-proxy 路由(相关机制见 docs/deploy-k-skill-proxy.md)。 - 技能元数据:
highway-traffic-status的skill.json中声明了proxy/browser/lookup三个 profile,frontmatter 标注 locale 为 ko-KR、phase 为 v1(skill.json)。
这套「公开端点直连、密钥可被环境变量覆盖、错误类型化、空结果显式化」的实现方式,是 k-skill 中接入政府公开 API 类技能的典型范式,配合 highway-traffic-status/tests/test_highway_traffic.py 中基于 mock 的 URL 构造、解析与端到端 run 测试,可以离线复现并验证全部行为,无需真实网络。
【免费下载链接】k-skill한국인을 위한 스킬 모음집 - 에이전트를 한국인으로项目地址: https://gitcode.com/GitHub_Trending/ks/k-skill
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考