Files
cheney 221b1f8add feat: 引入 so-novel submodule 并提供非交互下载工具
- vendor/so-novel: 上游 v1.12.0 (规则驱动的书源抓取/下载引擎)
- tools/src: ToolMain 封装 search/download/toc/sources,stdout 只输出 JSON
- tools/build.ps1: 自动定位/下载 JDK21,按平台显式激活 javet 原生库 profile
- bin/novel.ps1|.cmd: 命令行入口(人读输出或 -Json)
- SKILL.md/README.md: 使用说明与下载原理分析
2026-11-04 15:12:10 +08:00

95 lines
5.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: ebook-novel
description: 用 so-novel 引擎聚合搜索多个中文小说书源并整本下载(txt/epub/html/pdf)。当用户要“找某本小说/下载小说/离线看/换个书源/转 epub/txt”时使用;本技能是本地 CLI 工具,不启动任何常驻服务。
---
# 小说搜索与下载(so-novel)
本仓库把 [so-novel](https://github.com/freeok/so-novel) 作为 submodule 内嵌,并用 `bin\novel.ps1`
封装成非交互 CLI。**不要**启动 so-novel 的 Web 模式(端口 7765),也**不要**去它的 TUI 菜单里操作。
## 什么时候用
- 用户给出书名/作者,想找可下载的书源或直接拿到整本文件;
- 需要特定格式(txt / epub / html / pdf),或需要按章节验证书源是否完整;
- 已有详情页链接,只想下载或看目录。
不适用:正版/付费平台(起点、微信读书等)的授权内容;无对应书源的外文小说。
## 标准流程
1. **搜索**(并发查全部激活书源,约 5–20 秒)
```powershell
pwsh bin\novel.ps1 search "<书名或作者>" -Limit 10 -Json
```
取 JSON 的 `results[]`(按相似度排序):`bookName` / `author` / `sourceName` / `url` / `latestChapter`。
2. **挑源**(关键,别拿到第一条就下)
- 书名、作者与用户要求一致(注意同名续作、同人:「诡秘之主:瑶光」不是「诡秘之主」);
- 同一本书多个源时,用 `toc` 比较章节数与首尾章节,取**章节最多、更新最近**的源;
- 若某源 `latestChapter` 明显落后(几个月前),换源。
3. **验证目录**(可选但推荐,目录页反爬/改版会导致下出空书或残书)
```powershell
pwsh bin\novel.ps1 toc "<详情页链接>" -Json
```
看 `chapters` 数量和 `firstChapters` / `lastChapters`,两个常见异常信号:
- **首章不是「第1章/序章」**(例如直接从“第101章”开始)→ 目录分页没抓全,会下出残书,换源;
- **开头是「后记/尾声」、结尾是「第1章」** → 站点倒序且规则没声明 `desc`,成品章节会反序,换源。
4. **下载**
```powershell
pwsh bin\novel.ps1 download "<详情页链接>" -Ext txt -Json
```
默认落盘 `<仓库>\books\书名(作者).txt`;`-Ext epub` 生成带封面的 epub;`-Out` 可换目录。
返回的 `file` 就是最终成品路径,`chapters` 是章节数,`ok=false` 时读 `error`。
5. **汇报**:给出书名、作者、来源站点、章节量级、文件绝对路径和大小;需要时说明换过几个源和原因。
## 输出契约
所有命令都是**一份 JSON**(`-Json`)或人读表格(默认):
```json
{"ok":true,"command":"download","bookName":"...","author":"...",
"sourceId":8,"sourceName":"笔趣阁365","ext":"txt",
"file":"...\\books\\书名(作者).txt","bytes":1870447,"seconds":4.51}
```
- 中文字段在 JSON 里是 `\uXXXX` 转义,解析后即为正确文本(这是为了绕开 Windows 控制台代码页)。
- `search` 的 `sources.failed[]` 列出抓取失败的源及错误(`403`、超时等),`sources.empty` 是返回空的源数;
这两个数字异常大说明网络/规则整体有问题,而不是这本书没有。
## 失败处理顺序
1. `search` 命中 0:换更完整的书名/作者,`-Limit` 调大,再试一次(不同源索引延迟不同)。
2. 命中的 URL 下载失败(`ok=false` 或 `toc` 为空):**换另一个源的 URL**,不要在同一源重试多次。
3. 连续多个源失败:加 `-Log` 看 `logTail` 里的上游报错,区分几种情况:
- `403` / `Just a moment...` → Cloudflare 或封 UA,该源需要代理/`cf-bypass`,直接跳过;
- 详情页书名或作者为空 → 站点改版,规则失效,跳过;
- `源站章节目录为空` → 目录页反爬,跳过。
4. 全书章节数正常但个别章节为空:上游允许单章失败跳过,成品仍可用;如实告知用户可能有缺章。
## 约束与礼貌
- 单机、串行使用;不要为了「快」把 `[crawl] concurrency` 调到 100,源站会限流并封 IP。
- 不要并发跑多个 `download`;同一本书不要反复重下(`books/` 里已有就直接报告路径)。
- 不要修改 `vendor/so-novel` 里的代码;需要新能力就加到 `tools/src/skills/novel/ToolMain.java`。
- 上游更新后必须重建:`pwsh tools\build.ps1 -Force -RefreshRules`(详见 README 的维护章节)。
## 一次完整的例子
```powershell
pwsh bin\novel.ps1 search "三体" -Limit 5 -Json
# -> results 里 刘慈欣《三体1:地球往事》/ 笔趣阁52 / https://www.52bqg.com/book_40390/
pwsh bin\novel.ps1 toc "https://www.52bqg.com/book_40390/" -Json
# -> chapters: 37,开头「第1章 1科学边界」,结尾「第37章 后记」——顺序正常
pwsh bin\novel.ps1 download "https://www.52bqg.com/book_40390/" -Ext txt -Json
# -> file: D:\workbench\ebook-skill\books\三体1:地球往事(刘慈欣).txt
```
对照:同一本书在「少年小说网」目录是倒序(开头“后记”、结尾“第1章”),下载会得到反序章节;
若某个源的目录条数明显偏少、首章又不是第 1 章,说明分页没抓全,都会产出残书——这两种情况都应换源。