news 2026/9/18 9:45:05

朝鲜王朝实录(조선왕조실록)搜索技能实战:基于 k-skill 的 sillok_search.py 官方站点抓取方案

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
朝鲜王朝实录(조선왕조실록)搜索技能实战:基于 k-skill 的 sillok_search.py 官方站点抓取方案

朝鲜王朝实录(조선왕조실록)搜索技能实战:基于 k-skill 的 sillok_search.py 官方站点抓取方案

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

本技术指南围绕 k-skill 开源仓库中的joseon-sillok-search技能展开,讲解如何借助 @nomadamas/k-skill CLI 与随附的 sillok_search.py 脚本,直接读取韩国国史编纂委员会(국사편찬위원회)官方实录网站sillok.history.go.kr的公开 HTML,完成关键词检索、王名/年份过滤、结果摘要与文章详情(국역/원문)抽取。读完本文,你将掌握该技能的全部 CLI 参数语义、端到端工作流、底层 HTML 解析原理、分页与过滤算法,以及通过单元测试验证的工程细节,可直接复制命令用于真实的历史文献检索场景。

一、技能定位:面向 Agent 的官方实录检索器

joseon-sillok-search是 k-skill 技能集(仓库目录joseon-sillok-search/,同时以packages/k-skill-cli/skills/joseon-sillok-search/形式随 CLI 分发包捆绑)中的一个history 类别技能,其skill.json中的 profile 为lookup(查询类),面向ko-KR韩国语场景,版本标记为 v1。

它的核心定位在 instruction.md 中说得非常直白:不依赖任何第三方 API、不维护本地索引,而是直接对官方站点的「搜索结果显示页 HTML」和「文章详情页 HTML」进行抓取与解析。v1 的能力范围被刻意收敛为:

  • 关键词检索(keyword search)
  • 可选的按王名过滤(--king
  • 可选的按公元纪年过滤(--year
  • 整理检索结果的标题 / 摘要 / 原文链接
  • 从文章详情页抽取 국역(韩文翻译)与 원문(汉文原文)摘要

该技能适合以下典型用户请求(文档「When to use」章节给出的示例):

  • "조선왕조실록에서 훈민정음 찾아줘"(在实录里找训民正音)
  • "세종 때 실록에서 측우기 관련 기사 검색해줘"(检索世宗时期实录中测雨器相关条目)
  • "1443년 조선왕조실록 기록 찾아줘"(查找 1443 年的实录记录)
  • "정조실록에서 수원 관련 기록 몇 개 보여줘"(从正祖实录中展示几条水原相关记录)

这些自然语言请求由 Agent 理解后,转换为下文将详述的 CLI 调用。

二、运行前提与输入参数

2.1 前提条件(Prerequisites)

按官方文档,运行本技能只需满足:

  • 可用的互联网连接(所有数据均实时抓取自官方站点);
  • python3运行环境;
  • 无需任何 API Key,这也是该方案最大的易用性来源;
  • helper 脚本sillok_search.py已随@nomadamas/k-skillCLI 打包,也可直接阅读仓库源码 joseon-sillok-search/scripts/sillok_search.py。

脚本对第三方依赖的要求极低:requests属于可选依赖(源码第 17-20 行以 try/except 方式导入,缺失时自动退化为标准库urllib),因此即便在无pip install的裸环境里也能运行。

2.2 输入参数总览

文档「Inputs」章节与源码 parse_args 函数 共同定义了完整的命令行参数面:

参数必选类型默认值说明
--query✅ 必选str发送给实录站点的检索关键词,缺省直接报错
--king可选str王名过滤,如세종정조세종실록,自动做别名规范化
--year可选int(正整数)公元纪年过滤,如1443;源码用positive_int校验,传入0或负数会抛出ArgumentTypeError(有对应测试test_rejects_non_positive_year
--limit可选int(正整数)5(源码DEFAULT_LIMIT返回结果条数上限
--type可选kwkk= 국역(韩文翻译)检索,w= 원문(汉文原文)检索
--timeout可选int(正整数)30秒(源码DEFAULT_TIMEOUTHTTP 超时时间

需要特别说明--type的语义:官方站点对「翻译文本」与「原文文本」分别建了检索通道,选择w意味着直接在汉文原文里匹配关键词(例如检索「임진왜란/壬辰倭乱」的古文写法时更精确)。

三、端到端工作流

文档「Workflow」章节给出了 5 步标准流程,与源码 search_sillok 函数 的实现一一对应:

  1. 发起官方检索:通过 CLI 调用npx -y @nomadamas/k-skill@0 exec joseon-sillok-search scripts/sillok_search.py -- --query "...",向官方检索 endpoint 发送 POST 请求;
  2. 解析结果页:从返回的搜索 HTML 中解析出结果总数、按王分类的统计(왕별 분류)、文章链接与摘要;
  3. 收窄结果:按需追加--king--year再次过滤(这一步既可以放在请求时,也可以依赖脚本内置过滤);
  4. 逐篇抓详情:对选中的每篇文章,打开/id/<article_id>详情页,抽取 국역 与 원문 摘要;
  5. 结构化输出:将所有数据组装为结构化的 JSON 返回给调用方。

3.1 CLI 实战命令

文档「CLI examples」提供的四条命令可直接复制运行,覆盖了参数组合的主要形态:

# 基础关键词检索(默认检索 국역、最多 5 条) npx -y @nomadamas/k-skill@0 exec joseon-sillok-search scripts/sillok_search.py -- --query "훈민정음" # 组合过滤:王名 + 公元年份 + 条数 npx -y @nomadamas/k-skill@0 exec joseon-sillok-search scripts/sillok_search.py -- --query "훈민정음" --king "세종" --year 1443 --limit 3 # 王名别名自动规范化("세종실록" 会被归一为 "세종") npx -y @nomadamas/k-skill@0 exec joseon-sillok-search scripts/sillok_search.py -- --query "측우기" --king "세종실록" --limit 5 # 切换到汉文原文检索通道 npx -y @nomadamas/k-skill@0 exec joseon-sillok-search scripts/sillok_search.py -- --query "임진왜란" --type w --limit 5

命令语法说明:exec joseon-sillok-search scripts/sillok_search.py指示 k-skill CLI 在技能目录内执行scripts/sillok_search.py,双横线--之后是传给该脚本的自身参数。若不用 npx,也可直接以python3 scripts/sillok_search.py --query "훈민정음"的方式运行仓库内的源码。

四、源码深度解析:抓取与解析原理

4.1 网络层:浏览器式请求头 + 双客户端容错

源码顶部常量定义了三个核心 URL(与文档「Notes」章节完全一致):

  • 官方主页:https://sillok.history.go.kr
  • 检索 endpoint:https://sillok.history.go.kr/search/searchResultList.do(POST)
  • 文章详情:https://sillok.history.go.kr/id/<article_id>(GET)

DEFAULT_HEADERS模拟了真实浏览器的请求特征:Accept-Language: ko-KRReferer: https://sillok.history.go.kr/main/main.do,以及一个完整的 Chrome/136 macOS UA 串。这类「以公开 HTML 表面为数据源」的方案必须携带贴近真实浏览器的头,以提高请求被站点正常响应的概率。

HTTP 客户端采用双通道策略(build_http_client / fetch_text):

  • 优先使用requests库(若已安装)发起 POST/GET;
  • requests不可用、或抛出传输类异常(RequestExceptionOSError),自动回退到标准库urllibOpenerDirector,其内部挂载了HTTPCookieProcessor(CookieJar 维持会话)与HTTPSHandler(默认 TLS 校验);
  • 值得强调的是:HTTP 错误(HTTPError)不会触发回退而是直接抛错,TLS 校验始终开启(ssl.create_default_context()),这一点被测试test_build_opener_keeps_default_tls_verificationtest_fetch_text_keeps_requests_tls_verification_enabled显式锁定,防止未来改动意外关闭证书校验。

4.2 检索请求体构造

build_search_payload(源码 L423-L431)构造的 POST 表单字段为:

字段含义
topSearchWord用户关键词检索词
pageIndex页码(从 1 开始)分页游标
initPageUnit0初始化分页单元
typek/w检索通道
sillokTypeS实录类型
topSearchWord_ime<span class="newbatang">…</span>高亮样式用的 HTML 回显

4.3 搜索结果页解析

parse_search_results(源码 L334-L378)通过三组正则从结果页 HTML 中抽取信息:

  • 结果总数:优先读取隐藏字段totalCount,失败则回退到页面文本「검색결과N개」;
  • 分通道计数:按--type选择隐藏字段countK(국역)/countW(원문)/countM/countC中的对应项,用于后续分页总数计算;
  • 王别分类统计:匹配class="cate-item"的链接(其 href 为javascript:searchCategory('...')),解析出形如「세종 (5)」的分类标签与命中数,存入categories列表;
  • 结果条目:匹配class="result-box"区块,从中提取goView('<article_id>', n)跳转函数里的文章 ID、class="subject"的标题、class="text"的摘要,并拼接出https://sillok.history.go.kr/id/<article_id>形式的正式链接。

4.4 标题元数据解析:王名规范化与纪年换算

这是本技能最具历史领域特色的部分。实录条目标题形如:

세종실록 102권, 세종 25년 12월 30일 경술 2번째기사 / 훈민정음을 창제하다

parse_result_title_metadata(源码 L312-L331)要做三件事:

  1. 拆分文章标题:以/为界,取后半段作为article_title(如「훈민정음을 창제하다」);
  2. 解析王名与纪年:用正则捕获「XX N년」或「XX 즉위년」(即位年),即位年视为第 1 年;
  3. 换算公元年份:查KING_ACCESSION_YEARS表拿到该王即位时的公元年,再执行gregorian_year = accession_year + regnal_year(即位年特殊处理为直接取即位年)。该表覆盖从 태조(1392) 到 순종(1907)、순종부록(1910) 的全部 25 位王及增修/修正本。

王名别名规范化由 normalize_king_name 与KING_ALIASES表实现:用户输入「세종실록」「정조실록」「연산군일기」等带后缀写法时,会被统一映射为 canonical 王名(如세종연산군),而「선조수정실록」→「선조수정」、「순종실록부록」→「순종부록」等特殊卷也都有独立条目。这正好印证了文档「Response policy」中「输入的王名稍有不同也能归一到 canonical 王名」的承诺。

4.5 过滤与分页算法

filter_results(源码 L381-L397)在客户端侧做二次过滤:王名用规范化后的名称做精确匹配,年份则按换算出的公元年份做精确相等比较。

search_sillok中的分页主循环(源码 L471-L487)是关键设计点:

  • pageIndex=1开始逐页抓取;
  • 首页返回后,用type_count / 每页条数向上取整算出总页数,并受MAX_PAGES = 20硬上限保护;
  • 当过滤条件命中率低时,会继续向后翻页,直到累计过滤结果达到limit或当前页为空——测试test_search_continues_to_later_pages_for_filtered_matches专门验证了「第 1 页全是非目标王条目、第 2 页才命中」时会正确请求第 2 页;
  • 最终只对filtered_results[:limit]中的文章逐篇抓取详情页。

4.6 详情页解析与文本清洗

parse_detail_page(源码 L400-L420)从/id/<article_id>页面提取:

  • headerclass="title"中的日期行(含「세종실록102권, 세종 25년 12월 30일 경술 2/2 기사 / 1443년 명 정통(正統) 8년」这种中韩历法对照信息);
  • title<h3>中的文章标题;
  • 국역 文本class="view-item left"区块内class="view-text"
  • 원문 文本class="view-item right"区块内class="view-text"
  • 분류(分类)class="view_font02"的列表项(如「어문학-어학(語學)」)。

清洗层(clean_text/clean_article_text,源码 L203-L219)依次执行:剔除 HTML 注释 → 将<br>转成换行 → 剥离标签 → 反转义实体 → 压缩空白。clean_article_text还会用DETAIL_FOOTER_PATTERN精确裁剪掉文末的版本注记与版权行——形如【태백산사고본】 33책 102권 42장 A면 【국편영인본】 4책 533면的书志学信息以及ⓒ 세종대왕기념사업회版权脚注,避免污染正文;测试test_strips_bibliographic_and_copyright_footer_from_article_text验证了该行为。

4.7 结构化 JSON 输出

脚本最终输出(search_sillok 返回值)的顶层结构为:

{ "query": "훈민정음", "type": "k", "filters": { "king": "세종", "year": 1443, "limit": 3 }, "total_results": 21, "type_count": 11, "returned_count": 3, "categories": [ { "label": "세종", "count": 5, "token": "..." } ], "items": [ { "article_id": "kda_12512030_002", "url": "https://sillok.history.go.kr/id/kda_12512030_002", "title": "세종실록 102권, ... / 훈민정음을 창제하다", "article_title": "훈민정음을 창제하다", "summary": "이달에 임금이 친히 언문 28자를 지었다.", "king": "세종", "regnal_year": 25, "gregorian_year": 1443, "detail": { "header": "...", "title": "...", "translated_text": "...", "original_text": "...", "classification": "어문학-어학(語學)" }, "excerpt": "국역正文前 280 字符(无 국역 时退化为 summary 前 280 字符)" } ] }

excerpt字段的设计值得一提:它取详情页 국역 正文的前 280 字符作为可读摘要,若详情缺失则回退到结果页 summary,保证 Agent 始终有可供引用的文本。任何网络/解析异常都会以{"error": "..."}JSON 形式输出到 stderr 并返回退出码 1(main 函数)。

五、测试验证:工程可靠性的保障

仓库在 scripts/test_sillok_search.py 中提供了完整的unittest测试套件(与 scripts/test_sillok_search.py 同源,构建了含真实 DOM 结构的样例 HTML),覆盖以下关键行为:

  • 标题元数据解析세종 25년→ 纪年 25、公元 1443;문종 즉위년→ 纪年 1、公元 1450(即位年特殊规则);
  • 结果页解析:总数 21、국역 计数 11、分类「전체/세종/정조」及其计数、条目 ID 与 URL 拼接;
  • 王/年过滤king="세종", year=1443后只保留目标条目kda_12512030_002
  • 详情页解析:국역/원문/분류 三字段抽取,以及书志脚注与版权行的剥离;
  • 网络回归:默认 TLS 校验保持开启、requests传输失败时回退urllib、构建客户端时 opener 始终可用;
  • 跨页翻页:过滤命中在第 2 页时能正确继续抓取;
  • 参数校验--year 0被拒绝。

这些测试既可作为回归保护,也是理解各解析函数输入输出契约的最佳样例——例如 SAMPLE_DETAIL_HTML 中「훈민정음을 창제하다」对应的 원문 为「○是月, 上親制諺文二十八字。」,完整示范了韩汉对照的抽取结果。

六、响应策略与完成标准

文档「Response policy」与「Done when」明确了 Agent 的行为边界,也是使用本技能时应遵循的规则:

  • 回答内容:以官方实录站点确认的「文章标题 + 链接 + 摘要 + 详情摘要」为核心,链接统一整理为https://sillok.history.go.kr/id/...格式;
  • 年份语义--year一律按公元纪年过滤(源码中的gregorian_year字段即由此而来);
  • 王名归一세종세종실록等输入差异会自动归一化;
  • 不做过度推断:v1 明确不实现semantic search、embedding、大规模索引构建(源码也确无相关代码),只做公开 HTML 表面抓取;
  • 空结果如实报告:命中 0 条时不得臆造内容,原样返回空结果;
  • 判定完成的条件:官方站点真实检索到 ≥1 条结果、必要时王/年过滤已生效、至少包含 1 条文章详情摘要、链接均为官方/id/格式。

七、适用边界与注意事项

  • 该方案依赖官方站点的公开 HTML 结构与接口稳定性,站点改版可能导致解析正则失效,届时需同步更新 sillok_search.py 中的正则常量;
  • 抓取属于对公网资源的轻量访问,脚本已内置 30 秒超时、20 页翻页上限,建议按需控制--limit,避免大规模并发请求;
  • 数据版权归国史编纂委员会所有,文中链接指向官方页面,适合学术检索与个人研究用途;
  • 若使用 CLI 分发版本,指令以npx -y @nomadamas/k-skill@0 instruct joseon-sillok-search输出的最新内容为准;helper 文件清单可通过npx -y @nomadamas/k-skill@0 files joseon-sillok-search查看(见 SKILL.md)。

从「关键词 → 王/年过滤 → 详情抽取 → 结构化 JSON」的完整链路看,joseon-sillok-search是一个无密钥依赖、工程化程度高(正则解析、纪年换算、双客户端容错、280 字符摘要、跨页翻页均有源码与测试支撑)的领域查询技能,可作为 Agent 在历史文献检索场景中的开箱即用组件。

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

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/18 9:43:03

2026年学术诚信红线:这些行为会让你延毕,okbiye帮你守住学术底线

2026年了&#xff0c;学术诚信要求比以往任何时候都严——双审严查&#xff08;重复率AIGC痕迹&#xff09;、文献真实性核查、数据可重复性要求、学术不端零容忍。很多同学不是故意学术不端&#xff0c;而是因为不懂规则、用错工具、图省事踩了红线&#xff0c;结果轻则重写&a…

作者头像 李华
网站建设 2026/9/18 9:42:07

智慧实验室整体规划与落地:协议选型、告警链路与LIMS集成

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/18 9:41:09

YOLOv8环境配置完全指南:从虚拟环境到GPU推理

从零开始配过几套深度学习环境之后&#xff0c;你会发现YOLOv8的环境配置卡住人的地方往往不是YOLOv8本身&#xff0c;而是它底下的PyTorch、CUDA、Python版本这一串“配套零件”之间的排列组合。这个系列前面我们已经把Python、Anaconda和基础工具链理清了&#xff0c;这篇就专…

作者头像 李华