k-skill 实战:韩国高速公路实时路况与 CCTV 查询技能 highway-traffic-status 深度解析
2026/9/19 8:10:22 网站建设 项目流程

k-skill 实战:韩国高速公路实时路况与 CCTV 查询技能 highway-traffic-status 深度解析

【免费下载链接】k-skill한국인을 위한 스킬 모음집 - 에이전트를 한국인으로项目地址: https://gitcode.com/GitHub_Trending/ks/k-skill

本篇技术指南以 k-skill 仓库中的highway-traffic-status技能为对象,完整讲解它如何基于韩国道路公社(data.ex.co.kr)实时交通量 API 与国家交通信息中心 ITS(openapi.its.go.kr)CCTV 信息 API,实现高速公路区间(콘존)级速度、交通量、拥堵等级(通畅/缓行/拥堵)以及坐标范围内的 CCTV 流元数据查询。读完本文,你将掌握该技能的完整命令行用法、JSON 输出字段、密钥与代理策略、失败模式,并通过仓库源码与测试用例理解其底层实现原理,能够直接在自己的 Agent 工作流中调用或复刻这一"零密钥、纯标准库"的查询方案。

技能定位:查询专用,不越界

highway-traffic-status是一个典型的lookup(查询)导向技能,其核心职责清晰且边界严格:

  • 通过韩国道路公社公共数据门户(data.ex.co.kr)的实时交通量 API,查询全国高速公路区间(콘존)级的速度、交通量、通行时间与拥堵等级(원활 通畅 / 서행 缓行 / 정체 拥堵);
  • 通过国家交通信息中心 ITS(openapi.its.go.kr)的 CCTV 信息 API,查询指定坐标范围内的高速公路 CCTV 名称、经纬度与 HLS 流地址。

技能元数据在 skill.json 中明确声明了三条画像:proxybrowserlookup,类别为transit、地区为ko-KR、版本阶段为v1,并在描述中限定了触发条件:"用户询问高速公路拥堵、交通状况、线路/区间通行、高速公路 CCTV 时使用;不用于公共交通路线或汽车路径导航"。

技能本身是查询专用的:路径规划、导航、通行费计算均不在其范围内。完整指令文档见 highway-traffic-status/instruction.md,CLI 按运行时(generic / dolshoi)装配后的指令快照见 packages/k-skill-cli/test/snapshots/highway-traffic-status.generic.md 与 packages/k-skill-cli/test/snapshots/highway-traffic-status.dolshoi.md。

适用与不适用的场景

**适用(When to use)**的典型用户表达:

  • "现在京釜高速堵吗?"
  • "告诉我首尔收费站那边的拥堵情况"
  • "西海岸线上行通行如何?"
  • "给我看板桥附近的高速公路 CCTV"

**不适用(When not to use)**时,指令明确要求转派给其他技能:

  • 公共交通路线 →korean-transit-route
  • 汽车路径/导航 →kakao-map
  • 市区道路、一般国道的详细通行(v1 以高速公路为中心)

运行环境与前置条件

技能的运行门槛极低,这是它的一大特点:

  • Python 3.9+,且仅使用标准库。实现脚本 highway_traffic.py 顶部导入的模块只有argparsecontextlibjsonospathlibsysurllib系与xml.etree.ElementTree,没有任何第三方依赖,无需pip install
  • 用户无需 API 密钥。两个上游接口均可用公开演示密钥test直接访问(脚本头部注释记录该结论于 2026-07-21 实测确认)。因为属于公开端点,该技能不经过 k-skill-proxy 转发,直接调用上游,这符合仓库"免费 API 直连、付费/受限 API 走代理"的代理策略。

可选的密钥环境变量(应对演示密钥回收/配额)

为了在演示密钥test被回收或遭遇配额限制时平滑切换,指令提供了两个可选环境变量:

环境变量对应上游获取途径
KSKILL_EXDATA_API_KEYdata.ex.co.kr 实时交通量在韩国道路公社公共数据门户注册后签发个人认证密钥
KSKILL_ITS_API_KEYopenapi.its.go.kr CCTV 信息在国家交通信息中心开放数据门户获取个人认证密钥

此外,脚本还会读取~/.config/k-skill/secrets.env中同名键。这一机制的实现位于resolve_api_key()(highway_traffic.py):优先取环境变量,若为空则解析secrets.env(支持#注释行、KEY=VALUE键值对、去除引号包裹),解析函数load_secrets()用朴素行解析实现,无需额外配置库。

注意:指令同时强调硬性安全规则——绝不在聊天、文件或 shell 参数中以明文形式索取、打印或存储凭据。个人密钥应通过环境变量或 secrets 文件注入,而不是写死在命令行里。

两条上游 API 的技术要点

指令文档的 "Data sources & fallback order" 一节给出了明确的调用顺序与技术细节,脚本 docstring 与测试进一步印证:

1. 实时交通量快照(韩国道路公社)

GET https://data.ex.co.kr/openapi/odtraffic/trafficAmountByRealtime?key=<key>&type=json[&numOfRows=N&pageNo=N]
  • 返回全国 VDS 实时快照(JSON 格式,list数组),并非按区间维度分页下发;线路/区间过滤由 helper 在客户端本地完成
  • 无效密钥时接口仍返回 HTTP 200,但响应体为{"code": "ERROR", "message": "인증키가 유효하지 않습니다."},需按类型化错误处理。
  • URL 构造逻辑见build_traffic_url():固定携带keytype=json两个查询参数,密钥为空时自动回退到演示密钥test

2. CCTV 信息(国家交通信息中心 ITS)

GET https://openapi.its.go.kr:9443/cctvInfo?apiKey=<key>&type=ex&cctvType=1&minX=..&maxX=..&minY=..&maxY=..&getType=json
  • 这是一个值得注意的:尽管请求中带了getType=json成功响应实际是 XML。因此脚本必须"先按 XML 解析,失败再回退到 JSON 错误包"(见normalize_cctv()的实现顺序)。
  • 无效密钥返回 HTTP 401,JSON 体为{"header": {"resultCode": 4005, ...}}
  • 参数type--road-type控制:ex(高速公路,默认)/its(国道)/allcctvType=1固定为路况 CCTV。

两个上游的演示密钥test均有效;当环境变量/密钥文件中存在个人密钥时,优先使用个人密钥。

实时交通量/路况查询实战(traffic 子命令)

基本用法

npx -y @nomadamas/k-skill@0 exec highway-traffic-status scripts/highway_traffic.py -- traffic --route 경부 --text

这条命令表示:通过 CLI 的exec子命令执行技能捆绑的 helper 脚本(这是指令强制要求的调用方式——捆绑助手只能通过npx -y @nomadamas/k-skill@0 exec highway-traffic-status scripts/<file> -- <args>执行,不得假定仓库相对路径或已安装技能的相对路径;如需文件系统路径,用npx -y @nomadamas/k-skill@0 path highway-traffic-status <relative-path>解析)。

参数详解

参数说明
--route线路名片段(如경부京釜、서해안西海岸)或线路编号(如0010
--keyword区间(콘존)名称关键字(如서울TG양재
--limit N输出行数上限,默认 30
--text输出人类可读的摘要;不传该标志则输出结构化 JSON

--route的匹配逻辑在filter_traffic()中实现:对每条记录,若路由名中包含该关键字路由编号与之完全相等即命中;--keyword则对conzone_name(区间名)做子串匹配。测试用例test_filter_traffic_by_route_matches_name_or_number验证了按名称경부命中 2 条、按编号0150精确命中"서해안선"各 1 条;test_filter_traffic_by_keyword_matches_conzone验证关键字서울TG命中"서울TG-양재IC"区间。

JSON 输出字段

不传--text时,脚本输出一个结构化的 JSON 对象,外层包含:

{ "result": "ok", "total_matched": 2, "rows": [ ... ], "source": "data.ex.co.kr trafficAmountByRealtime" }
  • resultokempty(无匹配时);
  • total_matched:过滤后的总匹配数(不受--limit影响);
  • rows:实际输出的记录数组;
  • source:数据来源端点标识。

rows中每条记录的字段(由normalize_traffic()生成,已做类型与标签归一化):

字段含义
route_name线路名称(如경부선
route_no线路编号(如0010
conzone_name区间(콘존)名称
conzone_id区间编号
direction方向(상행上行 /하행下行)
speed_kmh速度(km/h),无法解析时为null
traffic_volume交通量(车辆数)
travel_time_sec平均通行时间(秒)
congestion拥堵等级(원활通畅 /서행缓行 /정체拥堵)
observed_at观测时间(由stdDate日期与stdHour时刻拼接)

上游原始字段的映射关系:speedspeed_kmhtrafficAmouttraffic_volumetimeAvgtravel_time_secupdownTypeCodedirectiongradecongestionstdDate+stdHourobserved_at。等级与方向码的映射常量定义在脚本顶部:

GRADE_LABELS = {"1": "원활", "2": "서행", "3": "정체"} DIRECTION_LABELS = {"S": "상행", "E": "하행", "N": "상행", "W": "하행"}

测试test_normalize_traffic_converts_numbers_and_grade_label验证了该映射:grade1원활、grade3정체、方向码E하행S상행

文本摘要格式

--text模式调用render_traffic_text()输出一行一条的记录,格式为:

[경부선 하행] 구서IC-영락IC: 원활 · 89km/h · 교통량 20 (기준 20260721 1530)

即:[线路名 方向] 区间名: 拥堵等级 · 速度 · 交通量 (观测时间);速度为None时显示"속도 미상"(速度未知)。

CCTV 元数据查询实战(cctv 子命令)

基本用法

坐标范围(经度--min-x/--max-x、纬度--min-y/--max-y)是必填的。用户只说出地名时,Agent 应将其转换为大致的 bounding box 再调用:

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

上述示例覆盖首尔市区周边(约东经 126.9–127.2、北纬 37.3–37.6)范围。

参数与坐标校验

  • --road-typeex(高速公路,默认)/its(国道)/all
  • 响应的url字段是HLS 流地址;流媒体的实际播放由用户环境(浏览器/播放器)负责,技能只提供元数据;
  • 坐标校验在_validate_bbox()中强制执行(构造 URL 前调用):四个坐标必须齐全、min < max,且必须落在韩国范围(经度 124.0–132.0、纬度 33.0–39.5)内,否则抛出带明确提示的HelperError
KOREA_LON_RANGE = (124.0, 132.0) KOREA_LAT_RANGE = (33.0, 39.5)

测试test_cctv_bbox_bounds_are_validatedtest_cctv_bbox_must_stay_in_korea_range分别覆盖了"min 不小于 max"与"超出韩国坐标范围"两类非法输入。

JSON 输出与 XML 解析

不传--text时输出:

{ "result": "ok", "cameras": [ { "name": "[수도권제1순환선] 성남", "url": "http://cctvsec.example/stream1", "format": "HLS", "lat": 37.42889, "lon": 127.12361 } ], "source": "openapi.its.go.kr cctvInfo" }

normalize_cctv()的解析策略(与 ITS 接口"声称 JSON 实则 XML"的行为对齐):

  1. 若响应体以{开头,尝试按 JSON 解析——能解析出header.resultMsg说明是错误包,抛"认证密钥需确认"的HelperError
  2. 否则按 XML 解析,遍历所有<data>节点,提取cctvnamecctvurlcctvformatcoordxcoordy;经纬度无法转为 float 的记录会被跳过;
  3. 根节点不是response且没有任何 CCTV 时,抛"响应中无数据"错误。

测试test_normalize_cctv_parses_xml_metadata用一段含 2 个<data>节点的 XML 验证了解析结果;test_normalize_cctv_raises_on_key_error_json验证 4005 错误 JSON 的正确报错;test_normalize_cctv_raises_on_unexpected_body验证<html>类非预期响应会报"无法解析"错误。

结果摘要规则(Agent 行为约束)

指令对查询结果的呈现方式提出了三条明确约束,确保 Agent 不擅自加工数据:

  1. 照搬上游等级,不加自身判断:拥堵状态直接采用上游grade字段,映射为通畅/缓行/拥堵展示,不自行推断或修改;
  2. 必须附带观测时间:同时告知observed_at基准时刻,并明确这是"实时快照";
  3. 驾驶安全:若判断用户处于驾驶中,建议其使用语音或由同行乘客确认,不鼓励驾驶中操作。

从运行时装配指令(generic/dolshoi 快照)看,该技能被定性为 lookup 导向:完成的定义是"数据已获取,并连同来源(表/端点、周期、单位)一起总结,且将任何请求的后续动作连接到支持它的官方界面",而不是输出结果后就宣告结束。

失败模式与容错处理

指令文档用表格形式完整列出了各类失败场景及 Agent 应采取的应对动作,是运行期排障的核心依据:

场景应对动作
空结果(result: "empty"提示无符合条件的区间/CCTV,建议放宽线路名与坐标范围后重试
认证密钥错误("인증키가 유효하지 않습니다" / ITS 401 resultCode 4005)提示演示密钥可能被回收,指导用户申请个人密钥并配置环境变量
上游 HTTP 错误/超时提示稍后重试,并说明可能是上游维护中
JSON/XML 解析失败提示可能被拦截或接口格式变更,建议报告 issue
坐标范围错误输出韩国范围(经度 124–132、纬度 33–39.5)及 min<max 的校验提示

这些错误在代码层全部收敛为统一的HelperError异常:http_get_text()把 HTTP 401 或响应体含"인증키"的情况、其他 HTTP 错误、连接失败分别转成带中文提示的HelperErrorhttp_get_json()对非 JSON 响应报"可能被拦截或维护中"。run()顶层捕获HelperError后写入 stderr 并返回退出码 1,测试test_run_reports_helper_error_to_stderr对此做了断言。

源码实现细节:请求、归一化与主流程

在 highway_traffic.py 中,整个工具遵循清晰的分层设计:

  • 请求层build_traffic_url()/build_cctv_url()负责参数拼装与校验;http_get_text()urllib.request发起请求(携带自定义User-Agent: k-skill-highway-traffic/0.1),默认超时 30 秒(可用--timeout覆盖);
  • 归一化层normalize_traffic()把上游非规范字段(数值字符串、等级码、方向码、日期+时刻)整理为上文所述的稳定 JSON 结构;normalize_cctv()负责 XML/JSON 双格式识别;
  • 过滤与渲染层filter_traffic()做线路名/编号、区间关键字的客户端本地过滤;render_traffic_text()输出人读摘要;
  • 入口层parse_args()argparse子命令结构(traffic/cctv两个子解析器,公共参数--secrets-path--timeout--text);run()按子命令分发,统一以 JSON(含resulttotal_matched/camerassource)或文本方式输出,退出码 0 表示成功(含空结果),1 表示HelperError

其中"演示密钥直连、无需代理"的决策在脚本 docstring 中有明确记录:两个上游都可用演示密钥免注册工作,故按免费 API 代理策略直接调用上游(不注册 k-skill-proxy 路由);用户可用环境变量覆盖密钥以换取更高配额。

测试验证:行为即规格

test_highway_traffic.py 通过importlib从仓库路径动态加载脚本模块(不依赖 pip 安装),共覆盖四大类共 14 个用例:

  • URL 构造BuildUrlTests):验证交通量 URL 指向data.ex.co.kr/trafficAmountByRealtime且默认密钥为演示密钥test、用户密钥优先、CCTV URL 指向openapi.its.go.kr且参数齐全、坐标校验生效;
  • 解析与过滤ParseTests):验证数值转换、等级/方向标签映射、按线路名与编号过滤、按区间关键字过滤、XML 元数据解析、密钥错误 JSON 报错、非预期响应报错;
  • 端到端运行RunTests):通过mock.patch注入假响应,验证traffic子命令的 JSON 输出结构(rowstotal_matchedsource)、空结果显式标记emptycctv子命令的摄像头输出、错误写入 stderr 且退出码为 1、--text人类摘要渲染。

测试夹具中给出了真实的样例数据形态(如경부선区间서울TG-양재IC速度 35km/h、grade 3、timeAvg140 秒),可以直接用作本地联调或 mock 数据的参考。

使用边界与注意事项

  1. 更新前置:使用 k-skill CLI 工具前,应先执行npx -y @nomadamas/k-skill@0 update,确保 CLI 与所有编码 Agent 技能安装(包括~/.agents/skills)都是最新版本;技能完整指令通过npx -y @nomadamas/k-skill@0 instruct highway-traffic-status获取,捆绑文件清单用npx -y @nomadamas/k-skill@0 files highway-traffic-status查看(见 SKILL.md)。
  2. 代理策略:普通查询默认走托管的k-skill-proxyhttps://k-skill-proxy.nomadamas.org),无需用户 API 密钥;仅在自托管或使用替代代理时才设置KSKILL_PROXY_BASE_URL。而本技能因上游免费直连,是"跳过代理"的特例。
  3. CCTV 流地址时效性:ITS 返回的流 URL 是签名 URL,会随时间过期,需重新查询以刷新。
  4. 演示密钥风险:若上游调整演示密钥策略,本技能将退化为仅支持个人密钥(BYOK)模式;届时需重新评估是否将本技能纳入代理路由。

总体而言,highway-traffic-status是一个"小而完整"的技能范本:外部接口差异(XML 伪装成 JSON)、密钥分级(演示密钥兜底 + BYOK 覆盖)、错误分类(HTTP/认证/解析/坐标)、输出契约(结构化 JSON + 人读摘要)都在一个纯标准库 Python 文件中得到清晰实现,并配有完整的单元测试,非常适合作为 Agent 技能开发的参考蓝本。

【免费下载链接】k-skill한국인을 위한 스킬 모음집 - 에이전트를 한국인으로项目地址: https://gitcode.com/GitHub_Trending/ks/k-skill

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询