☰
WorkBuddy Skill 开发实战:自动更新 MyBooks 书库信息
2026/10/7 5:23:25 网站建设 项目流程

1. 从一条书库更新需求说起:为什么我选择用 WorkBuddy 来干这件事

手里攒了上千本电子书,散落在好几个硬盘和云盘目录里,文件名五花八门,有的带ISBN,有的只有书名加作者,还有的干脆就是“新建文件夹 (3)”。每次想找一本书,都得靠系统自带的搜索,搜出来的结果还经常对不上号。这个痛点我忍了很久,直到我开始用 MyBooks 这个本地书库管理工具来统一归档,情况才有所好转。但新的问题又来了:MyBooks 的书目信息需要手动一条条录入或者批量导入,格式稍微不对就报错,几百本书搞下来,人直接麻了。

后来我在折腾 WorkBuddy 的时候突然想到,这东西本质上是一个能调用各种 Skill 来完成具体任务的智能工作台,那我为什么不写一个专门用来更新 MyBooks 书库信息的 Skill 呢?说干就干,前前后后踩了不少坑,也积累了一些经验。这篇文章就是把我整个思路和实操过程完整地分享出来,从为什么要这么设计,到 Skill 怎么写,再到实际跑起来会遇到什么问题,全部摊开讲。如果你也在用 MyBooks 管理书库,或者想学习 WorkBuddy 的 Skill 开发思路,那这篇内容应该能帮你省下不少摸索的时间。

先简单交代一下背景。MyBooks 是一款本地化的个人书库管理软件,支持通过 CSV、JSON 等格式批量导入书籍元数据,包括书名、作者、出版社、ISBN、封面链接、阅读状态等字段。它的数据存储结构比较清晰,通常是一个主数据库文件加上若干资源目录。而 WorkBuddy 则是一个支持 Agent Skill 机制的工作台工具,你可以把它理解成一个能调度各种能力模块的“中枢”,每个 Skill 就是一项具体技能的封装,通过自然语言指令或者预设的触发条件来调用。把这两者结合起来,核心目标就是:让 WorkBuddy 自动读取我指定的书籍信息源,经过清洗和格式化之后,批量更新到 MyBooks 的书库中,全程不需要我手动干预。

这个方案适合什么人呢?第一类是有大量电子书需要整理归档的阅读爱好者,第二类是对 WorkBuddy 和 Agent Skill 开发感兴趣、想找一个真实场景练手的开发者,第三类就是单纯想了解怎么把两个工具串起来解决实际问题的人。不管你是哪一类,接下来的内容都会从最基础的概念讲起,逐步深入到具体的实现细节。

2. 整体设计思路:为什么不用脚本一把梭,而是走 Skill 路线

2.1 直接写 Python 脚本和封装成 Skill 的本质区别

最开始我其实是想直接写个 Python 脚本搞定的。逻辑也不复杂:读源数据、清洗字段、连 MyBooks 的数据库、批量写入。但真正动手之后发现,这种一次性脚本有几个绕不开的问题。第一是复用性差,下次换个数据源,比如从豆瓣导出的列表换成手动整理的 Excel,脚本就得大改。第二是没有交互能力,脚本跑完就完了,中间出了什么错、哪些书更新失败了,只能去看日志文件,不够直观。第三是没法跟其他工具联动,比如我想在更新之前先让 AI 帮我补全缺失的出版社信息,脚本就做不到了。

而 WorkBuddy 的 Skill 机制恰好能解决这些问题。Skill 本质上是对一组能力的封装,它定义了输入是什么、输出是什么、中间经过哪些处理步骤,而且可以被 WorkBuddy 的 Agent 调度。这意味着我可以用自然语言告诉 WorkBuddy“帮我把 D 盘那个书单更新到 MyBooks 里”,它会自动找到对应的 Skill 并执行。更重要的是,Skill 里面可以嵌套调用其他 Skill,比如先调用一个“数据清洗 Skill”处理格式,再调用一个“信息补全 Skill”填充缺失字段,最后才执行“MyBooks 更新 Skill”。这种组合能力是裸脚本给不了的。

从架构上看,我的设计是这样的:最上层是 WorkBuddy 的调度层,负责接收指令和分发任务;中间是 MyBooks 更新 Skill,负责核心的数据转换和写入逻辑;底层是 MyBooks 的数据库和文件系统,作为最终的数据落地目标。Skill 与 MyBooks 之间的通信方式,我选择了直接操作 MyBooks 的导入接口,也就是生成符合它格式要求的 CSV 文件,然后触发导入动作。这样做的好处是不需要去逆向它的数据库结构,降低了因为版本更新导致 Skill 失效的风险。

2.2 数据流向的完整链路拆解

整个数据流向可以拆成四个阶段。第一个阶段是数据采集,也就是确定书籍信息的来源。我的来源比较杂,有从各个平台导出的 CSV,有手动整理的 Markdown 表格,还有一些是从网页上复制下来的零散信息。第二个阶段是数据清洗和标准化,这是最耗时间的一步。不同来源的字段名称不一样,有的叫“书名”,有的叫“标题”,有的叫“Title”;日期格式也五花八门,有“2023-01-01”的,有“2023年1月1日”的,还有“Jan 1, 2023”的。这些都得统一成 MyBooks 能识别的格式。第三个阶段是数据校验,检查必填字段有没有缺失、ISBN 格式对不对、有没有重复记录。第四个阶段才是写入,生成导入文件并触发 MyBooks 的导入流程。

为什么要分这么细?因为每一步出错的概率都不一样,分开之后排查问题会容易很多。比如导入失败了,我可以先看是清洗阶段的问题还是校验阶段的问题,不用在一大坨代码里来回翻。而且这种分阶段的设计也方便后续扩展,比如以后想加一个“自动下载封面”的步骤,直接在清洗和校验之间插一个环节就行,不影响其他部分。

2.3 为什么选择 CSV 作为中间交换格式

在数据交换格式的选择上,我考虑过 JSON、XML 和 CSV 三种。JSON 的结构表达能力最强,嵌套字段处理起来很方便,但 MyBooks 的批量导入对 JSON 的支持不如 CSV 成熟,字段映射经常出问题。XML 就更不用说了,写起来啰嗦,解析也慢。CSV 虽然看起来简单,但胜在通用性强,MyBooks 对 CSV 的导入支持最完善,字段对应关系清晰,而且用 Excel 就能直接打开检查,调试的时候特别方便。

当然 CSV 也有它的坑。最大的问题就是特殊字符的处理,比如书名里带逗号、引号或者换行符,如果不做转义,导入的时候直接就把字段拆乱了。我的做法是在生成 CSV 的时候统一用双引号包裹每个字段,字段内部的双引号用两个双引号来转义。这个规则听起来简单,但实际写代码的时候很容易漏掉,后面讲实操的时候我会详细说。

3. Skill 的核心结构拆解:从定义到执行的完整链路

3.1 Skill 描述文件怎么写才能让 Agent 准确识别

WorkBuddy 的 Skill 需要一个描述文件来告诉 Agent 这个 Skill 是干什么的、什么时候该调用它、需要哪些输入参数。这个描述文件写得好不好,直接决定了 Agent 能不能在正确的时机触发这个 Skill。我一开始写得很随意,就一句话“更新 MyBooks 书库信息”,结果测试的时候发现 Agent 经常在该调用的时候不调用,不该调用的时候乱调用。

后来我仔细研究了 WorkBuddy 的 Skill 描述规范,发现关键在于要把触发条件和能力边界写清楚。比如我在描述里明确写了“当用户提到 MyBooks、书库更新、书籍信息导入、书目同步等关键词时触发”,同时限定了“仅处理本地文件系统中的书籍数据,不涉及在线书城操作”。这样 Agent 就能更准确地判断什么时候该用这个 Skill。另外输入参数也要定义清楚,我定义了三个参数:源数据文件路径(必填)、字段映射配置(可选,不填则使用默认映射)、是否跳过重复记录(可选,默认跳过)。

描述文件里还有一个容易被忽略的点,就是输出格式的声明。我明确写了 Skill 执行后会返回一个执行报告,包含成功更新的记录数、跳过的记录数、失败的记录数以及失败原因列表。这样 Agent 在执行完之后能把结果准确地反馈给我,而不是只说一句“执行完成”就没了。

3.2 输入参数的校验逻辑与容错设计

输入参数校验这块,我踩过一个很典型的坑。最开始我没做文件存在性检查,结果传了一个不存在的路径进去,Skill 直接报了一个底层的文件读取错误,堆栈信息一大堆,完全看不懂。后来我在 Skill 的入口处加了一层校验,按顺序检查:文件路径是否为空、文件是否存在、文件扩展名是否在支持列表中、文件大小是否超过限制。任何一项不通过,就返回一个人类可读的错误提示,而不是让底层异常直接抛出来。

容错设计方面,我遵循的原则是“能修复的自动修复,不能修复的明确报告”。比如源文件里有的行字段数量不对,少了一列或者多了一列,这种情况我会尝试根据表头来推断缺失的字段,如果推断不出来就跳过这一行并记录到失败列表里。再比如日期格式不统一,我会写一个解析函数,按优先级依次尝试几种常见的日期格式,能解析出来就自动转换,解析不出来就标记为待人工确认。

还有一个细节是编码问题。中文书籍信息里经常出现 GBK 和 UTF-8 混用的情况,如果不做处理,读出来的就是乱码。我的做法是先尝试用 UTF-8 读取,如果失败就回退到 GBK,再失败就尝试 GB18030。这个顺序是有讲究的,因为 UTF-8 的兼容性最好,优先尝试它出错的概率最低。

3.3 核心处理逻辑的分层设计

Skill 的核心处理逻辑我分成了三层。第一层是数据读取层,负责从不同格式的源文件中提取原始数据,统一转换成内部的数据结构。这一层的关键是抽象出一个通用的读取接口,不管源文件是 CSV、JSON 还是 Markdown 表格,读出来的都是同一种格式的字典列表。第二层是数据转换层,负责字段映射、格式标准化、数据清洗。这一层是整个 Skill 最核心也最复杂的部分,后面会单独展开讲。第三层是数据写入层,负责生成 MyBooks 能识别的导入文件并触发导入。

分层的最大好处是每一层都可以独立测试。比如我可以单独构造一组原始数据来测试转换层,不需要真的去读文件;也可以单独测试写入层,不需要每次都跑完整的流程。这在调试的时候能节省大量时间。另外分层之后,如果 MyBooks 的导入格式变了,我只需要改写入层,读取层和转换层不受影响。

4. 实操过程全记录:从零搭建一个可用的更新 Skill

4.1 环境准备与 WorkBuddy 的基础配置

在开始写 Skill 之前,得先把 WorkBuddy 的环境搭好。我用的版本是当前比较稳定的一个发行版,安装过程就不赘述了,按照官方指引一步步来就行。安装完成之后,第一件事是确认 Skill 的开发目录在哪里。不同版本的 WorkBuddy 目录结构可能略有差异,我这边是在用户目录下的一个隐藏文件夹里,里面有一个 skills 子目录,所有的 Skill 都放在这里。

然后是配置 Skill 的运行环境。我的 Skill 是用 Python 写的,所以需要确保 WorkBuddy 能调用到正确的 Python 解释器。这里有一个坑:如果你的系统里装了多个 Python 版本,WorkBuddy 可能会调用到不是你预期的那个。我的做法是在 Skill 的配置文件中显式指定 Python 解释器的绝对路径,避免歧义。另外依赖库也要提前装好,我用到的主要是 pandas 做数据处理、chardet 做编码检测、csv 模块做文件读写。这些库的版本最好也固定下来,避免因为版本差异导致行为不一致。

提示:在配置 Python 路径的时候,建议用绝对路径而不是相对路径,也不要用环境变量里的 python 命令。因为 WorkBuddy 执行 Skill 时的上下文环境可能和你手动打开终端时不一样,相对路径很容易找不到。

4.2 源数据读取与字段映射的实操细节

源数据读取这一步,我遇到的最大问题是字段名称不统一。举个例子,同样是书名这个字段,有的文件里叫“书名”,有的叫“标题”,有的叫“Title”,还有的叫“书籍名称”。如果每个来源都写一套读取逻辑,代码会变得非常臃肿。我的解决方案是建立一个字段映射表,把各种可能的字段名称都映射到统一的内部字段名上。

具体来说,我定义了一个字典,键是内部标准字段名,值是一个列表,包含了所有可能出现的别名。比如title对应的别名列表是["书名", "标题", "Title", "书籍名称", "book_name"]。读取的时候,遍历源文件的表头,对每个表头去映射表里查找它对应的标准字段名。如果找不到对应的标准字段名,就把这一列标记为“未识别”,在后续处理中忽略掉,同时在执行报告里提示用户有哪些列没有被识别。

这个映射表是可以扩展的。如果以后遇到了新的字段别名,只需要往列表里加一项就行,不需要改核心逻辑。我还做了一个小优化:映射的时候不区分大小写,也不区分全角和半角,这样能覆盖更多的变体情况。

字段映射完成之后,接下来是数据清洗。清洗的规则我列了一个清单,按优先级依次执行:去除首尾空白字符、合并连续空格、去除特殊不可见字符、统一标点符号(比如把中文逗号统一成英文逗号)、转换日期格式、校验 ISBN 格式。每一条规则都对应一个独立的函数,方便单独测试和调整。

4.3 数据校验与去重逻辑的实现

数据校验这块,我重点做了三件事。第一是必填字段检查,MyBooks 要求书名和作者是必填的,如果这两个字段有一个为空,这条记录就会被标记为无效并跳过。第二是 ISBN 格式校验,ISBN 有 10 位和 13 位两种格式,10 位的最后一位可能是数字或字母 X,13 位则全是数字。我写了一个校验函数,用正则表达式来匹配这两种格式,不匹配的就标记为格式错误。第三是重复记录检测,重复的判断依据是 ISBN 优先,如果 ISBN 为空则用“书名+作者”的组合来判断。

去重逻辑这里有一个细节需要注意:MyBooks 本身在导入的时候也有去重机制,但它的去重是基于它自己数据库里已有的记录来判断的。而我的 Skill 里的去重是在生成导入文件之前做的,目的是减少导入文件的大小和导入过程中的冲突。两者是互补的关系,不冲突。我的做法是,如果用户选择了“跳过重复记录”,那么在生成导入文件之前,先跟 MyBooks 的现有数据库做一次比对,把已经存在的记录过滤掉。如果用户没有选择跳过,那就全部保留,让 MyBooks 自己去处理冲突。

注意:跟 MyBooks 现有数据库比对的时候,不要直接去读它的数据库文件,因为不同版本的数据库结构可能不一样,而且直接读有可能造成文件锁冲突。我的做法是让 MyBooks 先导出一份当前书目的 CSV,然后我读这个 CSV 来做比对。虽然多了一步操作,但安全性和兼容性都好很多。

4.4 生成导入文件并触发 MyBooks 导入

生成导入文件这一步,核心是保证 CSV 的格式完全符合 MyBooks 的要求。我总结了几条必须遵守的规则:第一,文件编码统一用 UTF-8 with BOM,因为 MyBooks 在 Windows 环境下对不带 BOM 的 UTF-8 文件有时候会识别成乱码。第二,字段分隔符用英文逗号,每个字段用双引号包裹。第三,字段内部的双引号用两个双引号转义。第四,行尾换行符统一用\r\n,这是 Windows 环境下最兼容的换行方式。第五,表头的字段名必须和 MyBooks 要求的完全一致,大小写都不能错。

生成文件之后,触发导入的方式有两种。一种是手动导入,就是 Skill 生成好文件之后提示用户去 MyBooks 里手动操作导入。另一种是自动导入,通过命令行参数调用 MyBooks 的导入功能。我两种都实现了,默认走手动导入,因为这样更安全,用户可以先检查一下生成的文件有没有问题再导入。如果用户明确要求自动导入,才会走命令行方式。

自动导入的命令行参数需要参考 MyBooks 的官方文档,不同版本的参数可能不一样。我这边用的是类似mybooks-cli import --file "path/to/import.csv" --format csv --skip-duplicates这样的命令。执行之后会返回一个退出码,0 表示成功,非 0 表示失败。Skill 会根据退出码来判断导入是否成功,并把结果写入执行报告。

5. 常见问题与排查技巧实录

5.1 导入后中文显示乱码怎么办

这是最常见的问题,没有之一。乱码的根源基本上都是编码不一致。MyBooks 在读取 CSV 文件的时候,会按照它自己的默认编码来解析,如果你的文件编码和它的默认编码不一致,就会乱码。我的经验是,不管你的源数据是什么编码,最终生成的导入文件一定要用 UTF-8 with BOM。BOM 就像是给文件加了一个编码标识,告诉读取方“我是 UTF-8”,这样 MyBooks 就不会猜错了。

如果你已经导入了乱码的数据,也不用慌。先把 MyBooks 里刚导入的那批记录删掉,然后检查你的 CSV 文件编码。在 Windows 上可以用记事本打开文件,然后“另存为”,在编码选项里选择“UTF-8 with BOM”。在 Linux 或 Mac 上可以用file命令查看文件编码,用iconv命令转换编码。确认编码正确之后重新导入就行了。

5.2 字段错位和特殊字符导致的数据混乱

字段错位通常是因为 CSV 里的某个字段包含了逗号,但没有用双引号包裹,导致解析的时候把字段拆开了。比如书名是“活着,为了讲述”,如果没有用双引号包裹,解析出来就会变成两个字段。解决方法是生成 CSV 的时候强制给每个字段加双引号,不管它里面有没有逗号。这样做虽然会让文件稍微大一点,但能避免绝大多数字段错位的问题。

还有一种情况是字段里包含了换行符。有些书籍的简介是多行的,如果直接写进 CSV,就会导致一行变成多行,解析的时候直接乱套。处理方法是在写入之前把字段里的换行符替换成空格或者\n的转义形式。我一般替换成空格,因为简介里的换行大多数情况下只是排版需要,替换成空格不影响阅读。

5.3 Skill 执行超时或内存溢出的处理

当源数据量比较大的时候,比如上万条记录,Skill 执行可能会超时或者内存溢出。我遇到过一次,源文件有大概三万条记录,Skill 跑到一半直接卡死了。排查之后发现是两个问题:一是一次性把所有数据读进内存,二是没有做分批处理。后来我改成了流式读取,每次只读一批(比如 500 条),处理完一批再读下一批。这样内存占用就稳定了,不会随着数据量增长而暴涨。

超时的问题则是通过调整 WorkBuddy 的 Skill 超时配置来解决的。默认的超时时间可能只有几十秒,对于大批量数据处理来说不够用。我把它调整到了几分钟,同时在 Skill 内部加了进度日志,每处理完一批就输出一条日志,这样即使超时了,也能从日志里看到处理到哪一步了。

5.4 常见问题速查表

问题现象可能原因排查方法解决方案
导入后中文乱码文件编码不是 UTF-8 with BOM用记事本或file命令查看编码转换文件编码为 UTF-8 with BOM 后重新导入
字段错位字段内含逗号未转义打开 CSV 检查字段是否被拆分生成时强制给所有字段加双引号
部分记录导入失败必填字段为空或 ISBN 格式错误查看执行报告中的失败原因列表补全缺失字段或修正 ISBN 格式
Skill 执行超时数据量过大或超时配置过短查看日志确认处理进度改为分批处理并调整超时配置
重复记录被反复导入去重逻辑未生效检查是否选择了“跳过重复记录”启用去重选项或手动清理重复记录
日期格式无法识别源数据日期格式不在支持列表中查看失败记录中的日期字段在日期解析函数中添加对应的格式

6. 几个让我少走弯路的实操心得

6.1 先用小批量数据跑通全流程再上全量

这是我踩过的最大的坑。最开始我信心满满地拿全量数据去跑,结果中间某个环节出了问题,整个流程中断,我花了很长时间才定位到是哪个环节的哪条数据导致的。后来我学乖了,每次修改 Skill 之后,先用 10 条左右的小批量数据跑一遍全流程,确认没有问题再上全量。小批量数据最好覆盖各种边界情况,比如有缺字段的、有特殊字符的、有重复记录的,这样能一次性把大部分问题暴露出来。

6.2 执行报告要尽可能详细

执行报告是排查问题的重要依据,但很多人写 Skill 的时候不太重视这个。我一开始也是,执行报告就写个“成功更新 XX 条”,结果出了问题完全不知道是哪条记录、哪个字段出的问题。后来我把执行报告改成了结构化的格式,包含:总记录数、成功数、跳过数、失败数、失败记录明细(包含行号和失败原因)、未识别字段列表、处理耗时。这样不管出了什么问题,看报告就能快速定位。

6.3 版本兼容性要提前考虑

MyBooks 和 WorkBuddy 都会更新,更新之后接口或格式可能会变。我在 Skill 里加了一个版本检查的逻辑,启动的时候先检测 MyBooks 的版本号,如果版本不在已知兼容列表中,就给出警告提示,让用户确认是否继续。同时 Skill 的配置文件和映射表都做成了外部文件,这样即使需要适配新版本,也只需要改配置文件,不需要改代码。

6.4 日志分级输出便于排查

日志我分成了三个级别:INFO 记录正常流程的关键节点,WARN 记录不影响主流程但需要注意的问题(比如某个字段未识别),ERROR 记录导致记录处理失败的问题。默认只输出 INFO 和 ERROR,需要详细排查的时候可以打开 WARN 级别。这样平时用的时候日志不会太啰嗦,出问题的时候又能拿到足够的信息。

6.5 定期备份 MyBooks 数据库

虽然 Skill 本身不会直接修改 MyBooks 的数据库,而是通过导入接口来操作,但导入操作本身是有风险的。万一导入的数据有问题,可能会污染现有的书库。所以我在每次执行 Skill 之前,都会先让 MyBooks 导出一份当前书目的备份。这样即使出了问题,也能快速回滚。备份文件我建议按日期命名,保留最近几次的备份,太旧的可以删掉。

6.6 把 Skill 分享出去之前先做脱敏处理

如果你想把写好的 Skill 分享给其他人用,记得先做脱敏处理。主要是检查配置文件里有没有包含你自己的本地路径、MyBooks 的安装路径、数据库密码等敏感信息。我的做法是把这些信息都抽到单独的配置文件里,分享的时候只分享 Skill 的主体代码和一个配置模板,让使用者自己填写他们自己的路径和配置。这样既方便分享,又不会泄露个人信息。

这套方案我前前后后迭代了大概五六个版本,从最开始只能处理固定格式的 CSV,到现在能处理多种格式、自动清洗、自动去重、生成详细报告,中间踩的坑基本上都在这篇文章里了。如果你也在用 MyBooks 管理书库,或者正在学习 WorkBuddy 的 Skill 开发,希望这些经验能帮你少走一些弯路。后面我打算再加一个自动从公开书目数据库补全书籍信息的功能,等跑通了再来分享。

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

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

立即咨询