ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

cheap-gas-nearby 实战指南:基于韩国 Opinet 官方 API 的附近最便宜加油站查询包

cheap-gas-nearby 实战指南:基于韩国 Opinet 官方 API 的附近最便宜加油站查询包 cheap-gas-nearby 实战指南基于韩国 Opinet 官方 API 的附近最便宜加油站查询包【免费下载链接】k-skill한국인을 위한 스킬 모음집 - 에이전트를 한국인으로项目地址: https://gitcode.com/GitHub_Trending/ks/k-skillcheap-gas-nearby是 k-skill 仓库中面向韩国场景发布的 Node.js 包v0.4.0MIT 协议它以 한국석유공사韩国石油公社Opinet 官方开放 API 为价格数据源将「동네/역명/랜드마크小区/地铁站名/地标」这类自然语言位置串通过 Kakao Map 锚点搜索解析为 WGS84 坐标再经 WGS84→KATEC 坐标变换接入 Opinet 周边加油站检索最终按「价格优先、距离次之」返回排序结果。读完本文你将掌握该包的安装方式、完整调用链、9 个公开 API 的用途与源码实现细节并能在自己的 Node.js≥18项目或 AI Agent 技能中直接落地「查附近最便宜的加油站」这一实战能力。一、包定位与使用原则cheap-gas-nearby的核心职责非常聚焦用官方数据源回答「근처 가장 싼 주유소」附近最便宜的加油站在哪。它不是一个通用地图 SDK而是一条经过封装的「位置→坐标→油价→排序」流水线这在 README.md 的开篇就明确定位为使用韩国石油公社 Opinet 官方 API 查找附近最便宜的加油站。该包同时以cheap-gas-nearbySkill 的形式存在于仓库根目录的 cheap-gas-nearby/instruction.md 与 cheap-gas-nearby/SKILL.md 中服务于 AI Agent 场景并据此沉淀了四条硬性使用原则不自动追踪用户位置包本身不会读取或猜测设备定位Agent 必须先把「当前在哪」问清楚先问位置再搜索拿到 동네小区/ 역명站名/ 랜드마크地标/ 위도·경도经纬度中的任意一种格式后再动手价格数据优先走官方 Opinet Open API保证数据权威性与合法性位置字符串先经 Kakao Map anchor 搜索拿坐标再接 OpinetaroundAll.do周边查询两条链路分工明确。其中关于「默认产品为 휘발유汽油B027用户明确要 경유柴油才切换为 D047」的行为也写进了 instruction.md 的应答策略中。二、安装与运行环境包在发布后可像普通 npm 包一样安装npm install cheap-gas-nearby若要在本仓库内直接开发、调试该包例如配合 test/index.test.js 跑测试npm install运行环境要求可从 package.json 确认项目值版本0.4.0Node.js 要求18依赖全局fetch见下文入口文件src/index.js许可MIT发布文件src与README.md测试命令npm testnode --testLint 命令npm run lintnode --check语法检查需要特别说明的是包的 HTTP 层在 src/index.js 中直接使用options.fetchImpl || global.fetch因此必须运行在支持全局fetch的 Node 18 环境或者通过fetchImpl注入自定义实现测试正是利用这一注入点做 mock。三、整体架构与数据流从 src/index.js 的常量与函数组织可以看出整个查询是一条五段式流水线用户位置字符串서울역 / 37.55472,126.97068 │ ▼ ① Kakao Map 锚点解析仅字符串位置需要 m.map.kakao.com/actions/searchView?qquery → place-api.map.kakao.com/places/panel3/confirmId 取 WGS84 坐标 │ ▼ ② WGS84 → KATEC 坐标变换parse.js 中的 wgs84ToKatec │ ▼ ③ Opinet aroundAll.do 周边检索sort1 价格升序 │ ▼ ④ detailById.do 详情补全地址/电话/自助/洗车/保养/品质认证 │ ▼ ⑤ 价格优先、距离次之排序 → 输出 limit 条结果这一链路在 instruction.md 的 Workflow 一节有等价描述并在 test/index.test.js 中通过 mockfetchImpl一次串起了「서울역 搜索 HTML → 地点面板 JSON → aroundAll.do → detailById.do」的全部环节进行端到端验证。值得强调的是第 ① 步的健壮性设计resolveAnchorsrc/index.js会先对 Kakao 搜索结果按评分排序然后逐个尝试候选地点的面板接口——若第一个候选的 panel 返回 404或拿到的经纬度不是有限数值就自动回退到下一个候选全部失败才抛出No usable Kakao Map place panel was available for query。测试 index.test.js#L178-L254 专门验证了「首个候选无坐标时回退到第二候选」的行为。四、官方 API 表面与关键参数包所对接的官方接口在 README 与 instruction.md 中都有完整罗列整理如下均为包内部实际请求的真实端点用途端点Opinet 开放 API 说明https://www.opinet.co.kr/user/custapi/openApiInfo.do半径内加油站列表https://www.opinet.co.kr/api/aroundAll.do加油站详情按 IDhttps://www.opinet.co.kr/api/detailById.do地区代码https://www.opinet.co.kr/api/areaCode.doKakao Map 移动端锚点搜索https://m.map.kakao.com/actions/searchView?qqueryKakao Map 地点面板 JSONhttps://place-api.map.kakao.com/places/panel3/confirmId其中aroundAll.do的核心请求参数与取值范围在buildAroundSearchParamssrc/parse.js中有强制校验是调用该 API 的「契约」参数含义取值 / 约束out返回格式固定jsonx,y基准位置KATEC坐标必须是有限数值输出时保留 4 位小数radius搜索半径米正数最大 5000默认 1000超出即抛错prodcd油品代码B027汽油默认、D047柴油、B034高标号汽油、C004煤油、K015LPGsort排序方式1表示按价格排序certkey官方 API 密钥直连模式必填油品代码到语义键的映射在 src/parse.js 中定义B027→gasoline、B034→premiumGasoline、C004→kerosene、D047→diesel、K015→lpg详情接口返回的多油品价格会按此映射到统一的prices对象中。五、快速上手按位置字符串查询README 中的核心示例就是searchCheapGasStationsByLocationQuery——传一个「서울역」这样的自然语言位置其余坐标解析全部自动完成const { searchCheapGasStationsByLocationQuery } require(cheap-gas-nearby); async function main() { const result await searchCheapGasStationsByLocationQuery(서울역, { apiKey: process.env.OPINET_API_KEY, // 官方 API key或走代理模式时可省略 radius: 1000, // 半径米默认 1000最大 5000 productCode: B027, // 油品代码默认 B027汽油 limit: 3 // 最多返回条数 }); console.log(result.anchor); // 锚点name/sourceUrl/latitude/longitude 等 console.log(result.items); // 排序后的加油站列表 } main().catch((error) { console.error(error); process.exitCode 1; });该函数的实现src/index.js做了两件事先用parseCoordinateQuery判断入参是否本身就是坐标——形如37.55472,126.97068支持逗号、斜杠或空格分隔的字符串会被直接识别为经纬度从而跳过 Kakao 锚点搜索直接走坐标查询否则走resolveAnchor完成位置→坐标解析再调用坐标查询函数并在返回结果中额外附带anchor、anchorCandidates以及meta.resolvedQuery回填用户原始查询串。返回的result结构如下anchor解析后的锚点对象包含id、name、category、address、phone、latitude、longitude、sourceUrl形如https://place.map.kakao.com/1001items按价格升序、距离次之排序的加油站数组每个元素在detailLimit开启时还会合并详情字段见第七节metaproductCode、radius、total候选总数以及位置字符串模式下额外的resolvedQuery。六、坐标直查searchCheapGasStationsByCoordinates如果调用方如地图应用已经持有用户经纬度可以跳过锚点解析直接调用searchCheapGasStationsByCoordinatessrc/index.js。其可用选项与默认值如下选项默认值说明latitude,longitude必填WGS84 经纬度必须是有限数值radius1000搜索半径米≤5000productCodeB027油品代码sort1排序方式1 价格优先limit5返回条数最小 1detailLimit等于limit需要拉取详情的条数最小 00 表示不拉详情apiKey/certKey环境变量OPINET_API_KEY官方密钥直连模式必填limit与detailLimit都会经过normalizeCountOptionsrc/index.js的严格校验传入非有限数值会直接抛错如limit must be a finite number而不是静默返回空列表这一点有专门的测试用例覆盖index.test.js#L345-L367。函数内部流程为WGS84→KATEC 变换 → 调aroundAll.do→sortStationsByPriceAndDistance排序 → 对前detailLimit条并发拉取详情单个详情失败不会中断整体而是以{ error }占位→ 返回anchor内含katecX/katecY、items、meta三部分。七、9 个公开 API 逐一解析README「공개 API」一节列出了包的完整对外函数面结合源码与测试逐个说明其职责API位置职责与关键行为parseSearchResultsHtml(html)src/parse.js#L89-L116解析 Kakao 移动搜索 HTML抽取search_item base卡片中的id、name、category、address、phoneselectAnchorCandidate(query, items)src/parse.js#L180-L188对候选按评分排序后取第一名无候选则抛错normalizeAnchorPanel(panel, searchItem)src/parse.js#L190-L203把 Kakao 地点面板 JSON 规整为统一锚点对象point缺失时经纬度保持null而非强制 0有测试专门守护该行为wgs84ToKatec(latitude, longitude)src/parse.js#L254-L294WGS84→Bessel→KATEC 坐标变换返回{ x, y }buildAroundSearchParams(options)src/parse.js#L306-L324生成 OpinetaroundAll.do请求参数并做参数校验半径、坐标合法性parseAroundResponse(payload)src/parse.js#L355-L359解析RESULT.OIL列表兼容数组/单对象过滤掉无 ID 或价格非数值的脏数据normalizeDetailItem(payload)src/parse.js#L388-L418规整详情地址、电话、自助/洗车/保养/便利店/品质认证布尔位、按油品归类的prices与rawPricessearchCheapGasStationsByCoordinates(options)src/index.js#L220-L272坐标直查主入口见第六节searchCheapGasStationsByLocationQuery(locationQuery, options)src/index.js#L274-L305位置字符串查询主入口见第五节除此之外src/index.js的module.exports还额外导出了fetchSearchResults、fetchPlacePanel、fetchDetailById、rankAnchorCandidates、sortStationsByPriceAndDistance、buildAroundSearchParams以及四个 URL 常量AROUND_ALL_URL、DETAIL_BY_ID_URL、SEARCH_VIEW_URL、PLACE_PANEL_URL_BASE、DEFAULT_PROXY_BASE_URL方便上层做更细粒度的组合与二次开发。八、锚点候选的评分排序机制位置字符串能自动选中最合适的锚点依赖的是 src/parse.js#L118-L178 中的scoreAnchorCandidate评分体系。它对查询串与每个候选的名称/地址/分类做规范化NFKC 归一化 去标点小写后累加权重匹配条件加分名称与查询串完全一致1000名称恰为「查询串역」或去掉「역」后一致950名称以查询串开头800名称包含查询串600地址包含查询串120名称/分类命中 역·기차역·광장·공원·랜드마크 等锚点模式250名称/分类是 주유소加油站本身-200避免把结果站当锚点候选 ID 非纯数字-500分类含 기차역 / 전철역80同分时按韩文名称localeCompare(..., ko)稳定排序。测试 index.test.js#L37-L42 验证了「서울역」能正确选中 id1001 的 기차역 而非同名其他结果index.test.js#L256-L343 则验证了「강남역」场景下首选候选 404 后能按评分次序回退到「강남역 11번출구」的候选。九、WGS84→KATEC 坐标变换原理OpinetaroundAll.do要求 KATEC 坐标系下的x/y而 Kakao Map 锚点面板返回的是 WGS84 经纬度因此wgs84ToKatecsrc/parse.js#L254-L294是链路中不可省略的一环其实现分两步WGS84→Bessel 基准面转换采用三参数平移src/parse.js#L18 中的WGS84_TO_BESSEL [146.43, -507.89, -681.46]配合 WGS84 与 Bessel 椭球长半轴/扁率先用空间直角坐标平移得到 Bessel 经纬度纬度用迭代法求解收敛阈值1e-14最多 8 次迭代Bessel→KATEC 投影KATECKorea Transverse Mercator以 38°N、128°E 为中央纬线/经线KATEC_LAT0/KATEC_LON0假东 400000、假北 600000比例因子 0.9999经子午弧长展开式计算平面坐标src/parse.js#L9-L18。测试 index.test.js#L72-L77 给出了可复现的基准值(37.55472, 126.97068)转换结果为(309252.2237, 550779.9944)容差 ±1任何对该函数的改动都可以此回归校验。十、两种数据获取模式直连与代理cheap-gas-nearby支持两条访问 Opinet 的路径由 API key 的有无自动切换直连模式当options.apiKey/options.certKey或环境变量OPINET_API_KEY存在时useDirectApi判定见 src/index.js#L86-L88包直接请求https://www.opinet.co.kr/api/aroundAll.do拼接certkey与detailById.do。此时若缺少密钥会抛出OPINET_API_KEY or options.apiKey is required for official Opinet lookups.。代理模式没有密钥时请求改走默认代理https://k-skill-proxy.nomadamas.org常量DEFAULT_PROXY_BASE_URL可用options.proxyBaseUrl或环境变量KSKILL_PROXY_BASE_URL覆盖下的/v1/opinet/around与/v1/opinet/detail。这一默认路径同样写入了 instruction.md使用代理时用户侧无需自备OPINET_API_KEYAgent 直接可用。两种模式的切换点在fetchAroundStations与fetchDetailByIdsrc/index.js#L164-L202中代理模式下参数名对齐为x/y/radius/prodcd/sort/around与id/detail返回结构由parseAroundResponse/normalizeDetailItem统一规整对上层透明。请求层还内置了贴近真实浏览器的请求头普通文本请求使用带accept-language: ko的浏览器 UA 头Kakao 地点面板请求额外携带origin、referer、appVersion: 6.6.0、sec-ch-ua等头DEFAULT_PANEL_HEADERSOpinet JSON 请求则使用轻量的 JSON 头src/index.js#L19-L43。所有请求都支持options.headers合并与options.signal超时控制。十一、结果规范化品牌映射与多油品价格parseAroundResponse输出的每个周边条目含id、brandCode、brandName、name、price、distanceMeters、katecX、katecY。品牌代码到中文/韩文名称的映射表定义在 src/parse.js#L20-L31品牌代码名称SKESK에너지SK 能源GSCGS칼텍스HDO현대오일뱅크现代 OilbankSOLS-OILE1GE1SKGSK가스NHO농협알뜰农协实惠RTE자영알뜰个体实惠RTX고속도로알뜰高速实惠ETC자가상표自有品牌详情条目normalizeDetailItem在周边信息之上追加lotAddress/roadAddress地籍/道路名地址、phone、sigunCode、lpgYn、布尔型的isSelf自助、hasMaintenance保养、hasCarWash洗车、hasConvenienceStore便利店、kpetroCertified品质认证以及按PRODUCT_CODE_TO_KEY归类好的prices.gasoline/diesel/…和保留原始代码的rawPrices含tradeDate/tradeTime成交时间。mergeStationDetailsrc/index.js#L204-L218负责把两者合并并保证合并后price、distanceMeters仍以周边数据为准。排序函数sortStationsByPriceAndDistancesrc/parse.js#L420-L432的三级比较逻辑是先比价格升序再比距离升序最后按韩文名排序。测试 index.test.js#L96-L108 验证了「A10000011635 韩元/112.4m→ A10000031649 韩元/220m→ A10000021649 韩元/315m」这一价格优先、距离次之的期望顺序其中后两者同价时 220m 排在 315m 前面。十二、测试与可验证性包的测试用 Node 内置的node:test编写npm test即可运行测试文件 test/index.test.js 与 test/fixtures 目录下的固定样本anchor-search.html、anchor-panel.json、around-response.json、detail-a1000001.json、detail-a1000003.json共同覆盖了HTML 搜索卡片解析与锚点选优parseSearchResultsHtml/selectAnchorCandidate锚点面板规整与坐标缺失时的null保持WGS84→KATEC 数值基准309252.2237, 550779.9944aroundAll.do参数编码契约周边结果价格排序与详情字段补全自助、洗车、保养、品质认证、多油品价格带 mock fetch 的端到端调用链、锚点回退、评分序回退、非法limit拒绝。这些测试既是行为规格也是读者验证「包工作正常」的最直接手段。十三、失败模式与使用注意事项结合 instruction.md 的 Failure modes 一节与源码中的防御逻辑实际使用中需要关注以下风险点密钥缺失直连模式必须有OPINET_API_KEY或apiKey/certKey否则抛错代理模式下则要求代理服务可用且服务端已配置密钥Kakao 锚点歧义位置串模糊时可能选中错误坐标包会用评分与候选回退尽量缓解但仍建议 Agent 在结果可疑时向用户二次确认位置Opinet 响应波动官方 API 可能出现临时空结果或数据更新中parseAroundResponse会过滤无价格记录此时应如实告知「没找到」及下一步追问而不是编造结果参数边界radius超过 5000 米、坐标为 NaN、limit/detailLimit非有限数值都会立即抛错属于设计上的「快速失败」策略。对于 Agent 场景searchCheapGasStationsByLocationQuery的使用纪律是先问清当前位置与所需油品再调用默认按汽油B027、半径 1000 米、返回 35 条简洁整理即可满足绝大多数「附近最便宜的加油站」类需求。更完整的 Skill 级应答规范必问问题、字段整理模板、Done when 检查清单可继续参阅 cheap-gas-nearby/instruction.md 与 cheap-gas-nearby/SKILL.md。【免费下载链接】k-skill한국인을 위한 스킬 모음집 - 에이전트를 한국인으로项目地址: https://gitcode.com/GitHub_Trending/ks/k-skill创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表