ReadCat书源插件开发指南:三个方法讲透自定义小说书源的完整流程
【免费下载链接】read-cat一款免费、开源、简洁、纯净、无广告的小说阅读器项目地址: https://gitcode.com/gh_mirrors/re/read-cat
ReadCat是一款免费、开源、简洁纯净的小说阅读器,它的书源插件系统是这款应用最核心的能力:通过一段JavaScript插件代码,就能让阅读器支持任意小说网站。这篇文章带你反向拆解一个成品书源插件,看透它背后的三个核心方法和一份声明,然后亲手写出属于你的第一个自定义小说书源。
先看成品:一个书源插件长什么样
在动手之前,我们先见一见"成品"。一个标准ReadCat书源插件,本质上就是一个带有固定静态属性的JavaScript类。把它保存成.js文件,在应用的"设置→插件"里一键导入,就能立刻使用。
class MyBookSource { static ID = 'mybooksource-00000001'; static TYPE = 0; static GROUP = '我的书源'; static NAME = '示例书源'; static VERSION = '1.0.0'; static VERSION_CODE = 1; static PLUGIN_FILE_URL = ''; static BASE_URL = 'https://example.com'; constructor(config) { this.request = config.request; this.store = config.store; this.cheerio = config.cheerio; } async search(searchkey) {} async getDetail(detailPageUrl) {} async getTextContent(chapter) {} }是不是比想象中简单?这个类没有继承任何基类,也没有复杂的框架约束。接下来,我们像解谜一样,把每一块拼图拆开来看。
拆解第一层:那些静态属性是干什么的
类名上方那一串static属性,是插件在ReadCat眼中的"身份证"。在src/core/plugins/index.ts的Plugins类中,每次导入插件都会先执行一次严格的校验(_isPlugin方法),逐项检查这些属性是否存在、格式是否正确:
- ID:唯一标识,长度必须落在 16 到 32 位之间,只能由字母、数字、下划线和连字符组成,一旦重复会被拒绝导入;
- TYPE:插件类型,
0代表书源(BOOK_SOURCE),1是书城,2是TTS朗读引擎; - GROUP 与 NAME:分组名和显示名称,用于在插件列表里归类和展示;
- VERSION 与 VERSION_CODE:版本号和版本代号,未来在线更新时靠它们做版本比较;
- PLUGIN_FILE_URL:插件文件的更新地址,留空表示不支持在线更新;
- BASE_URL:书源请求的基础域名,ReadCat用它来拼接页面链接。
对照src/core/plugins/defined/plugins.d.ts里的PluginBaseProps定义,你会发现这七项就是全部清单。写错任何一项,导入时都会弹出明确的错误提示,这也是排错最快的地方——先检查静态属性,再检查方法。
拆解第二层:三个核心方法,就是一条完整阅读链路
接口定义在src/core/plugins/defined/booksource.d.ts中,总共只有三个方法,它们恰好串起了用户从找书到读书的全流程:
第一步,search(searchkey):搜索入口。用户输入关键词后,ReadCat会把这个词传给所有启用的书源,收集它们返回的结果列表。每个结果是一个SearchEntity,包含书名、作者、封面图、详情页链接和最新章节标题。
async search(searchkey) { const { body } = await this.request.get(`${this.BASE_URL}/search?q=${searchkey}`); const $ = this.cheerio.load(body); const results = []; $('.book-item').each((i, el) => { results.push({ bookname: $(el).find('.name').text(), author: $(el).find('.author').text(), coverImageUrl: $(el).find('img').attr('src'), detailPageUrl: $(el).find('a').attr('href') }); }); return results; }第二步,getDetail(detailPageUrl):详情与章节目录。传入搜索得到或书架中的详情页链接,返回完整的DetailEntity:书名、作者、封面、简介,以及最重要的——章节列表chapterList。每个章节是一个Chapter对象(标题、链接、序号),列表会按顺序显示在书籍详情页里。
async getDetail(detailPageUrl) { const { body } = await this.request.get(detailPageUrl); const $ = this.cheerio.load(body); const chapterList = []; $('.chapter-list a').each((i, el) => { chapterList.push({ title: $(el).text(), url: $(el).attr('href'), index: i }); }); return { bookname: $('.book-name').text(), author: $('.book-author').text(), coverImageUrl: $('.book-cover img').attr('src'), intro: $('.book-intro').text(), chapterList }; }第三步,getTextContent(chapter):正文解析。传入一个章节对象,返回一个字符串数组,每个元素是一段正文。ReadCat在src/core/plugins/index.ts中会自动对返回结果做HTML消毒处理(sanitizeHTML),过滤掉广告脚本和不安全的标签,所以你只需要把正文抽干净就行。
async getTextContent(chapter) { const { body } = await this.request.get(chapter.url); const $ = this.cheerio.load(body); const paragraphs = []; $('#chapter-content p').each((i, el) => { paragraphs.push($(el).text().trim()); }); return paragraphs; }src/core/plugins/booksource.ts里的isBookSource检查函数会逐一验证这三个方法是否都存在且为函数,缺一不可——所以哪怕你的书源只需要搜索功能,三个方法也得全部实现。
拆解第三层:构造函数里注入的四个工具
细心的你可能注意到了,构造函数接收了一个config对象,里面有四个开箱即用的工具:
- request.get / request.post:封装的网络请求工具,替你处理了跨域、代理、编码转换等问题,返回
{ body, code, headers }。这是书源插件唯一推荐的请求方式; - cheerio:服务端jQuery,用
$(...)选择器解析HTML,比正则抠标签可靠得多; - store:插件专用的小型存储空间(
setStoreValue / getStoreValue / removeStoreValue),适合缓存搜索历史、记住用户上次阅读位置,单个插件最多4MB,实现在src/core/plugins/store.ts; - nanoid / uuid:生成随机ID的小工具,做去重、拼请求参数时很顺手。
这些工具全部由createPluginClassInstance在src/core/plugins/index.ts中注入,插件代码运行在沙箱环境(vm2)里,既能访问这些安全能力,又碰不到主程序的其他部分,这也是ReadCat插件系统"纯净无广告"的底气所在。
验证环节:插件开发工具怎么用
写完之后怎么验证?ReadCat在设置页的"插件→开发"区域内置了插件开发工具:先导入.rpdt工具包,设置端口号,点击启动,就会弹出一个专门的调试窗口(对应源码electron/plugin-devtools.ts)。
调试窗口会实时显示插件代码里的console.log输出和报错堆栈,你可以直接对照报错信息修解析逻辑,改完重新导入即可,不需要重启应用。对于书源插件来说,这是最高效的排错手段。
从示例到实用:三个常见坑
最后分享三个新手最容易踩的坑,提前避开能省下大量调试时间:
- 详情页链接可能不是完整URL:网站内部链接常是
/book/123.html这样的相对路径,记得用BASE_URL拼接成完整地址再请求; - 封面图需要补全协议:很多网站的封面路径以
//开头,建议判断后补上https:,否则封面加载不出来; - 章节正文用
text()抽取后记得trim():否则每段开头结尾的空格会让阅读排版显得松散,ReadCat的消毒过滤也会把空段剔掉。
下一步,交给你的想象力
到这里,你已经完整拆解了一个书源插件:一份静态声明 + 三个核心方法 + 四个注入工具。这套模式同样适用于TTS朗读引擎和书城插件的开发,接口定义都集中在src/core/plugins/defined/目录下,随时可以翻阅参考。
现在就可以打开 ReadCat,从https://gitcode.com/gh_mirrors/re/read-cat克隆源码研究细节,或者直接新建一个.js文件开始你的第一个自定义小说书源。先从你平时用得最多的那个小说网站练手,把搜索和正文解析跑通,你就正式入门了。当你的书源能让别人一键导入、直接读书时,那种成就感绝对值得你此刻的尝试。动手吧,第一个书源插件正在等你写完它!🚀
【免费下载链接】read-cat一款免费、开源、简洁、纯净、无广告的小说阅读器项目地址: https://gitcode.com/gh_mirrors/re/read-cat
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考