kleague-results 使用指南:基于官方 K League JSON 端点的 Node.js 赛果与积分榜客户端
【免费下载链接】k-skill한국인을 위한 스킬 모음집 - 에이전트를 한국인으로项目地址: https://gitcode.com/GitHub_Trending/ks/k-skill
本指南围绕仓库中的 kleague-results 包 展开,它是一个封装韩国职业足球联赛(K리그)官方 JSON 接口的可复用 Node.js 客户端,可同时按日期查询比赛结果与当前积分榜。读完本文,你将掌握该包的安装方式、三个核心 API(getMatchResults/getStandings/getKLeagueSummary)的参数与返回值结构,并能结合 源码实现 与 测试用例 理解其日期过滤、球队别名匹配、状态归一化等底层原理。
为什么用官方 JSON 端点而不是 HTML 爬虫
K리그 官方站点的比赛数据是动态页面,传统做法是抓取 HTML 后解析 DOM。该包选择直接请求官方 JSON 接口,维护成本显著低于 HTML 爬虫——只要官方接口的响应结构不变,客户端就不需要频繁适配页面改版。包内硬编码了两个官方数据表面:
| 数据内容 | 端点 | 请求方式 |
|---|---|---|
| 赛程 / 比赛结果 | https://www.kleague.com/getScheduleList.do | POST,按月请求 |
| 球队积分榜 | https://www.kleague.com/record/teamRank.do | POST,携带 query 参数 |
这两个 URL 在 src/index.js 中定义为常量,测试用例也通过构造相同的端点来模拟请求(见 test/index.test.js)。
安装与运行环境
包要求Node.js 18+(在 package.json 的engines字段中声明),因为实现依赖原生global.fetch。安装方式:
npm install kleague-results如果你要在 Agent / CLI 场景中直接使用,可以全局安装:
npm install -g kleague-results该包是 k-skill 仓库中 kleague-results 技能 的数据层,技能文档建议在全局 Node 包缺失时先安装kleague-results,而不是用 HTML 抓取绕过(见 instruction.md)。
快速上手
下面是最小可用示例,同时演示了三个 API 的调用方式(摘自包 README):
const { getKLeagueSummary, getMatchResults, getStandings } = require("kleague-results"); (async () => { const results = await getMatchResults("2026-03-22", { leagueId: "K리그1", team: "FC서울", }); const standings = await getStandings({ leagueId: 1, year: 2026, }); const summary = await getKLeagueSummary("2026-03-22", { leagueId: "K리그1", team: "FC서울", includeStandings: true, }); console.log(results.matches[0]); console.log(standings.rows[0]); console.log(summary); })();从 package.json 可以看出,该包的main入口是src/index.js,发布时仅包含src目录和README.md,也就是说你安装后引入的正是下面将要分析的源码。
API 详解
包对外暴露三个主要异步函数,另有两个底层请求函数fetchScheduleMonth/fetchStandings供高级复用(见 src/index.js 的导出列表)。
getMatchResults(date, options)
按日期查询某一联赛的比赛结果,可选按球队过滤。
date:YYYY-MM-DD字符串或Date对象options.leagueId:1、2、K리그1、K리그2(也接受K1、KLEAGUE1、K2、KLEAGUE2等别名)options.team:球队简称 / 全名 / 球队代码别名,例如서울、FC서울、K09
返回对象包含queryDate、leagueId、filteredTeam(指定球队时的归一化结果)、clubs(参赛球队目录)和matches(规范化后的比赛数组)。
getStandings(options)
查询当前积分榜。
options.leagueId:1或2options.year:赛季年份,默认取韩国时区(Asia/Seoul)的当前年份。该默认值由源码中的getCurrentKoreaYear()实现,使用Intl.DateTimeFormat并指定timeZone: "Asia/Seoul"(见 src/index.js)
返回对象包含leagueId、year、isSplitRank、notice和rows(积分榜行数组)。
getKLeagueSummary(date, options)
一次调用同时返回「某日比赛结果 + 当前积分榜」,是 Agent 场景下最常用的组合接口。options与getMatchResults相同,额外支持includeStandings(默认true,源码中判断条件为options.includeStandings !== false,见 src/index.js)。
其组合逻辑是:先取比赛结果,再以查询日期中的年份为赛季年份调用积分榜(matches.queryDate.slice(0, 4)),并把比赛中出现的球队目录传给积分榜解析,从而保证两边球队名称一致(见 src/index.js)。
参数归一化:别名、日期与时区
leagueId 的别名解析
normalizeLeagueId维护了一张别名映射表(见 src/parse.js):
| 规范化结果 | 接受的别名 |
|---|---|
1(K리그1) | 1、K1、KLEAGUE1、K리그1 |
2(K리그2) | 2、K2、KLEAGUE2、K리그2 |
解析前会先做normalizeToken处理:NFKC 归一化、转大写、剔除除字母数字与韩文外的字符。因此"k league 2"也能被解析为2(测试用例 index.test.js 验证了这一点)。传入K리그3等无法解析的值会抛出leagueId must resolve to K League 1 or 2错误;空值则默认回退到1。
date 的解析与校验
normalizeDateInput支持YYYY-MM-DD和YYYY.MM.DD两种字符串格式,也接受Date对象;Date对象会按Asia/Seoul时区格式化为日期部分,避免时区偏移导致日期串位。字符串格式会经过严格的日历校验(含闰年判断),2026-13-40这类不存在的日期在发起任何网络请求之前就会被拒绝——测试 index.test.js 专门验证了这一点(断言fetchCalled为false)。
team 的别名匹配
buildClubDirectory从响应中的clubList构建球队目录,为每支球队收集teamId(如K09)、简称(서울)、全名(FC서울)等所有字段作为别名 token。resolveTeamQuery会用同样的 token 规范化方式匹配用户输入,因此서울、FC서울、K09都能命中同一支球队。注意:서울这类短名在 K리그2 中可能对应서울 이랜드,技能文档明确提示了这种歧义(见 instruction.md 的 Failure modes 一节)。
数据规范化:原始 JSON 如何变成结构化对象
官方接口返回的是面向展示的原始 JSON(可在 fixtures 中查看真实响应样本),包在src/parse.js中将其转换为便于程序消费的结构。
比赛状态映射
normalizeMatchStatus将官方状态码映射为统一语义(见 src/parse.js):
| 状态码 | state | label |
|---|---|---|
FE | finished | 종료(已结束) |
NS | scheduled | 예정(未开始) |
LIVE/IN | live | 진행 중(进行中) |
HT | halftime | 하프타임(中场休息) |
PP | postponed | 연기(延期) |
CAN | cancelled | 취소(取消) |
比赛对象字段
每场比赛被规范化为如下结构(见normalizeScheduleItem,src/parse.js):
leagueId、competitionName(如하나은행 K리그1 2026)、round、gameIddate(转为2026-03-22格式)、dateLabel、kickOffstatus:上述状态对象homeTeam/awayTeam:{ code, name, fullName, homepage, leagueId }score:{ home, away },未开赛时返回nullwinner:仅在已结束时返回home/away/draw,由determineWinner计算venue:{ shortName, name },如서울 월드컵 경기장audience、broadcastChannels(用//或|拆分的转播频道数组)matchCenterUrl:由gameId与meetSeq拼接的官方比赛中心链接
测试 index.test.js 用 2026-03-22 的 fixture 验证了完整映射:FC서울 主场 5:0 胜 광주、第 5 轮、状态FE/종료。
积分榜行对象
normalizeStandingsResponse将官方teamRank数组规范化为(见 src/parse.js):
rank、team(含 code / name / fullName)points(积分)、played(场次)、win/draw/loss(胜/平/负)goalsFor/goalsAgainst/goalDifference(进/失/净胜球)form:最近 6 场走势数组(game01~game06,值为승/무/패)homepage、stadium
此外会按rank升序、同分按积分降序、再按韩文队名排序,并用teamId去重。测试断言 2026 赛季 K리그1 有 12 行,서울 以 12 分居首、4 战全胜(见 index.test.js)。
底层请求细节
src/index.js中的requestJson统一处理 HTTP 调用:默认请求头包含accept-language: ko-KR以锁定韩文数据、user-agent: k-skill/kleague-results,并透传signal(AbortSignal)与可替换的fetchImpl(便于测试注入 mock)。
两个端点的请求方式不同,值得注意:
- 赛程接口:POST,body 为
{ year, month, leagueId },其中month会补零成两位(如"03")。由于该接口按月返回数据,包必须在客户端再次按请求日期精确过滤——测试用例专门断言了请求体包含"month":"03"(见 index.test.js)。 - 积分榜接口:POST,query 参数为
leagueId、year、stadium=all、recordType=rank。stadium=all表示当前为全主场口径的积分榜,包 README 的 Notes 部分对此有明确说明。
getMatchResults内部通过fetchScheduleMonth拿整月数据,再用normalizeScheduleResponse过滤出指定日期;getKLeagueSummary则在其上叠加积分榜调用,测试验证了组合调用时getScheduleList.do会被请求两次(一次在getMatchResults,一次在getKLeagueSummary内部,见 index.test.js)。
在 Agent / CLI 场景中的实际用法
该包是 k-skill 生态中 K리그 技能的数据层。技能工作流(见 instruction.md 与 docs/features/kleague-results.md)建议:
- 检查
npm root -g下是否存在kleague-results,缺失则npm install -g kleague-results,不要用 HTML 抓取绕过; - 调用
getKLeagueSummary一次拿到比赛与排名; - 将原始 JSON 整理为人类可读结果:主客队、开赛时间 / 是否已结束、比分、当前排名,若指定球队则只保留该队比赛;
- 保持回答紧凑:scoreboard 请求先给逐场一行摘要;单队请求先给该队比赛与当前排名。
在非包安装环境下,可用下面这种方式直接从全局 npm 目录加载模块(来自 docs/features/kleague-results.md 的示例):
GLOBAL_NPM_ROOT="$(npm root -g)" node --input-type=module - <<'JS' import path from "node:path"; import { pathToFileURL } from "node:url"; const entry = pathToFileURL( path.join(process.env.GLOBAL_NPM_ROOT, "kleague-results", "src", "index.js"), ).href; const { getKLeagueSummary } = await import(entry); const summary = await getKLeagueSummary("2026-03-22", { leagueId: "K리그1", team: "FC서울", includeStandings: true, }); console.log(JSON.stringify(summary, null, 2)); JS边界情况与失败模式
综合包 README 的 Notes 与技能文档的 Failure modes,使用中需要注意:
getScheduleList.do是月粒度接口,必须依赖库内按日过滤,不要假设返回即当日数据;- 查询日期在比赛开始之前时,返回的是
예정(scheduled)或진행 중(live)状态,score与winner为null; 서울这类短名跨联赛存在歧义,K리그2 场景下应确认是否指서울 이랜드;- 官方接口若改变
getScheduleList.do/teamRank.do的响应结构,则需要更新包内的解析逻辑(src/parse.js 是主要维护点); - 日期参数在请求前即被严格校验,非法日历日期不会触发网络请求。
本地验证方式
该包自带基于node:test的测试,覆盖了联赛别名解析、日期过滤、球队别名匹配、状态映射、积分榜结构以及「mock fetch 下的三 API 组合调用」等场景(见 packages/kleague-results/test/index.test.js)。测试依赖两份真实响应快照:schedule-kleague1-2026-03.json(2026 年 3 月 K리그1 赛程与俱乐部列表)和 standings-kleague1-2026.json(2026 赛季 K리그1 积分榜)。在包目录下执行即可运行:
npm test代码风格检查则通过node --check对三个 JS 文件做语法校验(npm run lint,见 package.json)。
总结
kleague-results 是一个「官方 JSON 端点 + 客户端归一化」的典型封装:对外提供三个语义清晰的异步 API,对内完成 leagueId 别名归一化、韩国时区日期解析、球队别名匹配、比赛/积分榜结构标准化。它规避了 HTML 爬虫的脆弱性,并把「月粒度数据按日过滤」「stadium=all积分榜」等官方接口特性封装成对调用方透明的能力。若你要在 Node.js 应用中集成 K리그 数据,或为 Agent 构建韩国体育信息查询能力,可直接参考本包 README、源码 与 测试 作为起点。
【免费下载链接】k-skill한국인을 위한 스킬 모음집 - 에이전트를 한국인으로项目地址: https://gitcode.com/GitHub_Trending/ks/k-skill
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考