全网网文爬虫与阅读管家 v2.2.0
> 遇到问题? 运行 python scripts/novel_scraper.py doctor 一键诊断 | 或跳转 FAQ
v2.2.0 新功能升级日志(2026-09-07)
🚀 新增功能
| 功能 | 说明 |
|---|---|
| 知识库同步 | 新增 kb-sync、kb-search、kb-sync-chapter、kb-probe 命令,支持将小说信息同步到国内主流知识库 |
| IMA 适配器 | 腾讯 ima 知识库 OpenAPI:创建笔记 → 关联知识库,凭证走环境变量或 ~/.config/ima/ |
| Dify 适配器 | Dify Knowledge API:create-by-text 写入 / retrieve 语义检索,Bearer DIFY_API_KEY |
| 本地知识库 | 默认可用:Markdown + JSON 索引,存储在 knowledge_base/ |
| 爬取源扩展 | 新增 69shu.pro、biquge.tv、biquge.info 等笔趣阁镜像,共 6 个预置镜像 |
| 番茄小说正式支持 | 新增 FanqieCrawler(需 Playwright),自动识别 fanqie 域名 |
| 69书吧支持 | 新增 Shu69Crawler(69shu 特殊解析),自动识别 69shu 域名 |
⚙️ 新增配置项
| 配置项 | 默认值 | 说明 |
|---|---|---|
kb_adapter |
local |
知识库适配器(local/ima/dify/all) |
kb_auto_sync |
false |
爬取后自动同步到知识库 |
kb_novel_tags |
网文,小说 |
同步时自动添加的标签 |
📚 新增命令
kb-probe # 测试知识库适配器可用性
kb-sync --book 书名 [--target local/ima/dify/all] # 同步小说到知识库
kb-search --query 关键词 [--target local] # 搜索知识库
kb-sync-chapter --book 书名 --chapter N # 同步单个章节到知识库
✅ 测试覆盖
新增 tests/test_v220_kb.py(知识库同步测试,离线)。
py -3.11 -m pytest tests -q # 预期 40+ passed
v2.1.0 优化升级日志(2026-08-27)
⚡ 性能优化(爬取约 3× 提速)
| 优化项 | 说明 |
|---|---|
| 并发爬取 | 章节正文改用线程池并发抓取(新配置 concurrency,默认 3,钳制 1-8),每线程自带礼貌延时;50 章从 ~75s 降到 ~27s |
| DB 连接复用 | 进程内复用单一 SQLite 连接(WAL 安全),原先每章爬取开 ~5 次连接,现在全程 1 次 |
| update O(n) 化 | 增量更新的已下载判断从 O(n²) any() 查找改为 O(1) 集合判断 |
| TTS 音频复用 | tts/listen 跳过已生成的音频(新增 --force 强制重生成),重跑不再浪费数分钟 |
| 单章自动重试 | 正文为空/过短自动重试 1 次(镜像偶发抖动不再丢章) |
🐛 Bug 修复
| Bug | 修复 |
|---|---|
| 失败章节被永久跳过(数据丢失) | 进度记录改为“连续前缀”语义:last_crawled_chapter 只推进到无缺口的最大章,中间失败章会被 update 重新爬取 |
| 章节范围语义不一致 | download/tts --chapters 优先按章节号匹配(与 crawl 一致),无命中时退化为位置序号(兼容旧行为) |
| 重叠范围重复导出 | parse_chapter_range 去重:1-3,2-4 不再导出/爬取两遍第 2-3 章 |
| TTS 失败残留不完整 mp3 | 合成失败时自动删除不完整音频,避免下次被误认为“已生成” |
| 搜索缺 lxml 崩溃 | 笔趣阁搜索解析器 lxml 未安装时降级到 html.parser |
| 字节码残留 | 全部 6 个脚本补 sys.dont_write_bytecode 防护;tests 新增 conftest 会话前后双清理 |
| 环境依赖 | 基线测试因缺 ebooklib 失败 1 例,已补装并验证 |
✅ 测试覆盖
新增 tests/test_v210.py(16 例,全离线):范围去重、连续前缀进度、章节号/位置双模式筛选、连接复用、重试、失败清理、音频复用、并发钳制、离线搜索解析、交付守卫、版本同步。
py -3.11 -m pytest tests -q # 30 passed
v2.0.1 修复日志(2026-07-28)
🐛 Word/EPUB 文字导出异常
症状:章节标题含 <、>、&(如"第一章 剑 & 魔 <初章>")时,导出的 EPUB 在 Word 阅读器中显示乱码或整章内容丢失。
根因:generate_epub() 直接将标题和段落插入 HTML,未转义 HTML 特殊字符,破坏标签结构。
修复:新增 _html_escape() 工具函数,所有标题/正文通过 html.escape(quote=True) 转义;新增中文 CSS 样式(Microsoft YaHei 字体、行距 1.7、段落首行缩进 2em),Word/EPUB 阅读器排版更美观。
🐛 音频生成异常
症状:① 6000+ 字的长章节 TTS 失败,提示 NoAudioReceived;② 网络瞬时失败直接放弃,无重试;③ Jupyter Notebook 中调用报 RuntimeError: asyncio.run() cannot be called from a running event loop。
根因:text_to_speech() 把整段文本一次性传给 edge-tts(单次上限 ~4096-10000 字符),且无重试机制,asyncio.run() 在已有 loop 中会抛错。
修复:
- 新增 _split_for_tts():按句子边界(。!?!?.)切分,每段 ≤ 3000 字符,超长句硬切
- 新增 _synthesize_one():指数退避重试 3 次(1.5s → 3s → 6s),识别 NoAudioReceived + 长度超限 不可重试错误
- 新增 _run_async_safely():检测已有 eventloop,自动切到独立线程跑 asyncio.run
- 清洗 10 种零宽/不可见字符(ZWSP/ZWNJ/ZWJ/LRM/RLM/BOM 等)+ emoji 表情
✅ 测试覆盖
新增 tests/test_export_audio_fix.py,14 个测试用例全部通过:HTML 转义、TTS 长文本分段、异步安全、EPUB 特殊字符处理、TXT 章节分隔、emoji/零宽字符清洗。
概述
覆盖"发现 → 添加 → 爬取正文 → 导出/听书 → 管理"全链路的网文工具。v2.0 核心补齐了章节正文爬取能力,download/tts 不再是空壳,全链路真正可用。
真实能力(实测 2025-07)
| 你想要 | 能做到吗 | 怎么做 |
|---|---|---|
| 搜索小说 | ✅ 起点可直搜 | fuzzy-search -q "凡人修仙传" |
| 用URL添加追更 | ✅ 没问题 | add-novel <URL> |
| 爬取章节正文 | ✅ 笔趣阁源可用 | crawl --book "书名" --chapters 1-50 |
| 终端阅读某章 | ✅ 没问题 | read --book "书名" --chapter 1 |
| 导出 EPUB/TXT | ✅ 含真实正文 | download --book "书名" --format epub |
| 转成MP3听书 | ⚠️ 需网络 | tts --book "书名" --chapters 1-10(国内可能需代理) |
| 增量追更 | ✅ 没问题 | update --book "书名" |
| 一键听书 | ✅ 全自动 | listen <URL或书名> |
| 交互向导 | ✅ 新手友好 | wizard |
| 看追更列表/统计 | ✅ 没问题 | list / stats |
| 在番茄/起点爬正文 | ⚠️ 需Playwright | config set enable_browser true(默认关闭) |
工作原理
搜索/URL → add-novel(记录元信息+来源) → crawl(爬目录+正文落盘) → download/tts
↓ ↓ ↑
数据库 novels/chapters ~/Novels/<书名>/chapters/ 读取正文文件
add-novel记录书名/作者/URL/平台,不下载正文crawl真正爬取:先抓目录页拿到章节列表,再逐章爬正文存为~/Novels/<书名>/chapters/0001_章节名.txtdownload/tts/read读取已爬取的正文文件生成 EPUB/MP3/终端输出- 断点续传:crawl 中断后重跑会自动跳过已爬章节
适用人群
- 追更多部连载小说的读者
- 喜欢睡前听书的用户
- 需要把网文导出到阅读器/手机的用户
- 想整理自己小说书架的用户
快速开始
1. 环境诊断(推荐先跑)
python scripts/novel_scraper.py doctor
会检查:依赖安装、笔趣阁镜像可用性、数据库、当前配置。缺什么装什么。
2. 安装依赖
# 一键全装
pip install requests beautifulsoup4 lxml ebooklib edge-tts
# 可选:音频合并(tts --merge 用)
pip install pydub
# 可选:浏览器渲染爬取(番茄/起点正文,默认关闭)
pip install playwright && playwright install chromium
3. 新手推荐:交互向导
python scripts/novel_scraper.py wizard
向导会引导你:搜书 → 选书 → 添加 → 爬取 → 听书,一条龙完成,不用记命令。
4. 命令一览
wizard # 交互向导(推荐新手)
fuzzy-search -q "凡人修仙传" # 搜索小说
add-novel <URL> [--crawl] # 添加追更(--crawl立即爬取)
crawl --book 书名 [--chapters 1-50] # 爬取正文(支持范围/断点续传)
update --book 书名 # 增量更新新章节
read --book 书名 --chapter N # 终端阅读某章
download --book 书名 [--format epub]# 导出EPUB/TXT
tts --book 书名 [--chapters 1-10] # 转语音(国内可能需代理)
listen <URL或书名> # 一键听书(自动add+crawl+tts)
list # 追更列表(含爬取进度)
stats # 阅读统计
remove --book 书名 # 删除小说
config list|get|set # 配置管理
mirrors list|test|use # 笔趣阁镜像管理
doctor # 环境诊断
# ── v2.2.0 新增:知识库命令 ──
kb-probe # 测试知识库适配器可用性
kb-sync --book 书名 [--target local/ima/dify/all] # 同步小说到知识库
kb-search --query 关键词 [--target local] # 搜索知识库
kb-sync-chapter --book 书名 --chapter N # 同步单个章节到知识库
真实可用流程示例
> 从零开始,走一遍"搜书 → 添加 → 爬取 → 导出/听书"的完整流程。
场景:我想爬《夜无疆》并导出 EPUB
第1步:搜索找到书
python scripts/novel_scraper.py fuzzy-search -q "夜无疆"
起点会返回结果。若搜不到,直接去笔趣阁网站找书URL。
第2步:添加到追更(用笔趣阁URL,可爬正文)
python scripts/novel_scraper.py add-novel "http://www.xbiqugu.la/134/134375/"
输出:
👉 访问: http://www.xbiqugu.la/134/134375/
✅ 已添加: 夜无疆 (笔趣阁) - 辰东
📖 那一天太阳落下再也没有升起……
第3步:爬取正文
python scripts/novel_scraper.py crawl --book "夜无疆" --chapters 1-50
输出:
👉 爬取目录: 夜无疆
✅ 目录共 788 章
👉 开始爬取正文: 50 章
██████████░░░░░░░░░░░░░░░░░░░░ 20.0% [10/50] 第10章 xxx
...
✅ 爬取完成: 50/50 章
ℹ️ 正文保存在: ~/Novels/夜无疆/chapters
第4步:导出 EPUB
python scripts/novel_scraper.py download --book "夜无疆" --format epub
输出:
✅ 已生成: ~/Novels/夜无疆/夜无疆.epub (50 章, 312 KB)
把 EPUB 传到手机/阅读器即可阅读。
第5步(可选):转语音听书
python scripts/novel_scraper.py tts --book "夜无疆" --chapters 1-10
> 国内网络若失败,设代理:config set proxy http://127.0.0.1:7890
一键流程
不想分步?用 listen 一步到位:
# 给URL,自动 add + crawl + tts
python scripts/novel_scraper.py listen "http://www.xbiqugu.la/134/134375/" --chapters 1-10
详细功能
模糊搜索
fuzzy-search -q "凡人修仙传" # 默认表格输出
fuzzy-search -q "修真 穿越" -n 10 # 多关键词,10条
fuzzy-search -q "系统" -p 笔趣阁,起点中文网 # 指定平台
fuzzy-search -q "凡人" --format json # JSON输出
平台状态:
- ✅ 起点中文网:可直搜(返回书名/作者/简介/URL)
- ⚠️ 笔趣阁:站内搜索接口已下线,但书页可爬正文。建议从首页/排行榜找URL后用 add-novel
- ⚠️ 番茄小说:需 CDP 浏览器(配合 web-access skill)
添加追更(add-novel)
add-novel <URL> # 仅添加元信息
add-novel <URL> --crawl # 添加后立即爬取前10章
add-novel <URL> --crawl --chapters 1-30 # 添加并爬取指定范围
自动识别平台(笔趣阁/起点/纵横等),解析书名/作者/简介。笔趣阁URL的详情页即目录页,可直接 crawl。
爬取正文(crawl)⭐ 核心功能
crawl --book "书名" # 爬取全部章节
crawl --book "书名" --chapters 1-50 # 爬取前50章
crawl --book "书名" --chapters 1-10,20,30-40 # 指定范围
crawl --book "书名" --from 100 # 从第100章开始
- 断点续传:已爬章节自动跳过,中断后重跑即可继续
- 进度条:实时显示
██████░░░░ 60% [30/50] 第30章 xxx - 礼貌爬取:每章间隔 1.5s(可配置
crawl_delay),随机 UA 轮换 - 正文清洗:自动去除笔趣阁水印、广告、导航文字,保留段落
- 单次限制:
config set max_chapters_per_run 100防止一次爬太多
正文存为 ~/Novels/<书名>/chapters/0001_章节名.txt。
增量更新(update)
update --book "书名" # 检查并爬取新章节
重新抓目录,对比已有章节,只爬新增的。
阅读(read)
read --book "书名" --chapter 1 # 终端阅读第1章
若该章未爬取,会自动爬取这一章再显示。
导出(download)
download --book "书名" --format epub # 导出EPUB(推荐)
download --book "书名" --format txt # 导出TXT
download --book "书名" --chapters 1-50 # 只导出指定范围
download --book "书名" --output D:/books # 指定输出目录
EPUB 含目录导航,章节正文分段排版,手机/平板/阅读器通用。
TTS听书(tts)
tts --book "书名" --chapters 1-10 # 转10章语音(已有音频自动复用)
tts --book "书名" --chapters 1-10 --merge # 合并为单个MP3
tts --book "书名" --voice zh-CN-YunxiNeural # 指定男声
tts --book "书名" --force # 强制重新生成已有音频
可用语音(edge-tts 中文神经语音):
- zh-CN-XiaoxiaoNeural 晓晓女声(推荐)
- zh-CN-YunxiNeural 云希男声
- zh-CN-XiaoyiNeural 晓伊女声(情感丰富)
> 国内网络:edge-tts 依赖微软云 speech.platform.bing.com,国内直连可能失败。
> 解决:config set proxy http://127.0.0.1:7890(你的代理端口)
一键听书(listen)
listen "http://www.xbiqugu.la/134/134375/" # URL:自动add+crawl+tts
listen "夜无疆" # 书名:跳过add,直接crawl+tts
追更列表与统计
list # 显示书名/作者/平台/爬取进度(已爬/总)/字数
list --all # 含未追更
stats # 总小说/章节/已爬/已读/已听/总字数
配置管理(config)
config list # 查看所有配置
config get tts_voice # 查看单项
config set proxy http://127.0.0.1:7890 # 设置代理
config set tts_voice zh-CN-YunxiNeural # 设置默认语音
config set crawl_delay 2.0 # 爬取间隔
config set max_chapters_per_run 100 # 单次最多100章
config set concurrency 3 # 爬取并发数(1=串行,建议≤5)
config set enable_browser true # 启用Playwright
镜像管理(mirrors)
mirrors list # 查看镜像列表(👉标记当前)
mirrors test # 测试所有镜像可用性
mirrors use 0 # 切换到索引0的镜像
笔趣阁镜像域名经常变动,失效时用 mirrors test 检查,mirrors use N 切换。
支持的平台
> 实测状态(2025-07)
| 平台 | 搜索 | 爬正文 | 元信息 | 反爬 | 说明 |
|---|---|---|---|---|---|
| 笔趣阁(聚合站) | ⚠️ 接口下线 | ✅ 可爬 | ✅ | ⭐ | 主力,从首页/URL添加,requests直爬 |
| 起点中文网 | ✅ 可直搜 | ⚠️ 需Playwright | ✅ | ⭐⭐⭐ | 正文JS渲染+VIP,建议用笔趣阁源 |
| 番茄小说 | ⚠️ 需CDP | ⚠️ 需CDP | ⚠️ | ⭐⭐⭐⭐ | 配合 web-access skill |
| 纵横中文网 | ❌ 下线 | ⚠️ 部分 | ⚠️ | ⭐⭐ | 接口404 |
| 晋江文学城 | ❌ 改版 | ⚠️ | ⚠️ | ⭐⭐ | 页面结构变更 |
| 飞卢/SF/刺猬猫/QQ阅读 | ❌ | ❌ | ❌ | ⭐⭐⭐ | 接口均已下线 |
关于笔趣阁聚合站:笔趣阁类站点收录正版网文的免费章节,反爬低、requests可直爬,是本工具的正文主力源。但这类站点域名经常变动,且版权为灰色地带,仅建议用于个人阅读。
FAQ - 常见问题解答
搜索相关
Q: 搜索返回0条结果?
A:
1. 起点搜索应正常返回结果
2. 笔趣阁站内搜索接口已下线(waps.php返回404),改用:浏览器去笔趣阁网站找书URL → add-novel <URL>
3. 关键词换通用一点的
Q: 怎么找到笔趣阁书的URL?
A: 浏览器打开 https://www.xbiqugu.la/,在首页/排行榜/分类里找到目标书,复制其详情页URL(形如 http://www.xbiqugu.la/134/134375/),然后 add-novel <URL>。
Q: 什么是 CDP/Playwright?我需要吗?
A: 用于爬取 JS 动态渲染的页面(番茄/起点正文)。默认关闭,因为笔趣阁源用 requests 就能爬。只有当你确实需要爬起点正文时才启用:config set enable_browser true(需先 pip install playwright && playwright install chromium)。
爬取相关
Q: crawl 报"目录爬取失败"?
A:
1. 镜像可能失效 → mirrors test 检查,mirrors use N 切换
2. 网络问题 → 检查网络/代理
3. 起点目录是JS渲染 → 用笔趣阁源,或启用Playwright
Q: crawl 中断了,已爬的会重复爬吗?
A: 不会。已爬章节标记为 is_downloaded=1,重跑 crawl --book xxx 自动跳过。这就是断点续传。
Q: 爬取速度慢?
A: v2.1.0 已支持并发爬取(默认 3 线程,约 3× 提速):config set concurrency 5 可再提速(不建议超过 5,易触发反爬)。每章仍有 crawl_delay(默认 1.5s)礼貌延时。设 1 退回串行。
Q: 爬到的正文有乱码/水印?
A: 工具已自动清洗笔趣阁水印和广告。若仍有残留,可能是新水印格式,可反馈优化 crawlers.py 的 WATERMARK_PATTERNS。
Q: 想爬很多章但怕一次中断?
A: config set max_chapters_per_run 100,单次最多100章,分多次跑,断点续传。
下载/导出
Q: download 说"尚无已爬取章节"?
A: 先 crawl --book xxx 爬取正文。download 读的是已爬的正文文件,没爬就导不出。
Q: EPUB 在哪?
A: ~/Novels/<书名>/<书名>.epub。用 --output 可改输出目录。
TTS听书(v2.0.1)
Q: TTS 失败"Cannot connect to speech.platform.bing.com"?
A: 国内网络问题。edge-tts 依赖微软云。v2.0.1 已自动重试 3 次(指数退避 1.5s → 3s → 6s)。仍失败则解决:
1. 设代理:config set proxy http://127.0.0.1:7890(你的代理端口)
2. 或换离线方案:pip install pyttsx3(质量一般但不联网)
Q: TTS 生成的音频在哪?
A: ~/Novels/<书名>/audio/0001_章节名.mp3。--merge 合并后为 ~/Novels/<书名>/<书名>.mp3。
Q: 长章节(6000+ 字)TTS 失败?
A: v2.0.1 已修复。自动按句子边界(。!?!?.)切分,每段 ≤ 3000 字符,分别生成后用 pydub 合并。无需手动处理。
Q: Jupyter Notebook 中 TTS 报 RuntimeError?
A: v2.0.1 已修复。检测到已有 eventloop 时自动切到独立线程跑 asyncio.run。
Q: EPUB 在 Word 里打开章节标题乱码?
A: v2.0.1 已修复。章节标题和正文都通过 html.escape() 转义,加载了中文 CSS 样式(Microsoft YaHei、行距 1.7、段落缩进)。
镜像/平台
Q: 笔趣阁镜像都不可用了?
A:
1. mirrors test 逐个测试
2. mirrors use N 切换到可用的
3. 都不行时,浏览器找到新的笔趣阁域名,编辑 scripts/crawlers.py 的 BIQUGE_MIRRORS 添加
Q: 想爬起点正版正文?
A: 起点正文是JS渲染+VIP章节。启用Playwright:config set enable_browser true(需安装),然后 crawl --book xxx。注意VIP章节需登录态,本工具只爬免费章节。
环境
Q: 'No module named X'?
A: pip install requests beautifulsoup4 lxml ebooklib edge-tts
Q: Windows 上 python3 不是命令?
A: Windows 用 python 而非 python3。
报错速查表
| 报错 | 原因 | 解决 |
|---|---|---|
ModuleNotFoundError |
依赖未装 | pip install 对应包 |
目录爬取失败 |
镜像失效/网络 | mirrors test 检查切换 |
尚无已爬取章节 |
没爬正文 | 先 crawl --book xxx |
Cannot connect to speech.platform.bing.com |
TTS网络 | config set proxy ... |
HTTP 404 |
URL失效/接口下线 | 换镜像或换URL |
请求超时 |
网络慢 | 检查网络,重试 |
域名解析失败 |
DNS问题 | 检查网络 |
数据库结构
SQLite data/novel_center.db:
| 表 | 用途 | 关键字段 |
|---|---|---|
novels |
小说主表 | title, author, platform, url, catalog_url, source_site, last_crawled_chapter |
chapters |
章节表 | novel_id, title, chapter_num, url, content_path, word_count, is_downloaded, is_read, is_listened |
settings |
配置 | key, value |
正文文件独立存于 ~/Novels/<书名>/chapters/,DB 只存相对路径,避免数据库膨胀。旧库(v1.x)首次运行自动迁移。
注意事项
| 项目 | 说明 |
|---|---|
| 版权 | 仅爬取免费章节,仅用于个人阅读,勿传播。VIP章节需正版授权 |
| 反爬 | 笔趣阁反爬低,但仍建议保持 crawl_delay≥1s,避免高频请求 |
| 磁盘 | 长篇小说正文约几MB,TTS音频可达数百MB,注意空间 |
| TTS耗时 | 1小时文本约20-30分钟生成 |
| 镜像 | 笔趣阁域名常变,失效用 mirrors 命令切换 |
| Playwright | 可选依赖,默认关闭。启用后可爬JS渲染页但增加~200MB |
架构(开发者参考)
scripts/
├── novel_scraper.py # 主CLI,命令路由(v2.2.0 新增 kb-* 命令)
├── search_engine.py # 跨平台搜索(起点+笔趣阁+番茄)
├── crawlers.py # 正文爬虫(笔趣阁主力+起点目录+通用+Playwright+69shu+番茄)
├── storage.py # 数据层(DB迁移+章节文件存储+断点续传)
├── config.py # 配置管理(settings表持久化,v2.2.0 新增知识库配置)
├── knowledge_sync.py # v2.2.0 新增:知识库同步(IMA/Dify/本地适配器)
└── ui.py # 终端UI(进度条/表格/交互向导)
references/
├── platforms.md # 平台状态与搜索接口
└── crawler_rules.md # 各平台解析规则与镜像列表
tests/
├── test_export_audio_fix.py # v2.0.1 修复验证(HTML 转义/TTS 分段/Jupyter/清洗)
├── test_v210.py # v2.1.0 回归(并发/重试/进度语义/筛选/守卫)
├── test_v220_kb.py # v2.2.0 新增:知识库同步测试(离线)
└── conftest.py # 字节码防护 + 会话前后缓存清理
测试
cd "D:/claude 开发/skill of me/web-novel-scraper"
py -3.11 -m pytest tests -q # 推荐(预期 40+ passed)
python tests/test_export_audio_fix.py # 也可单跑旧套件(需先 pip install ebooklib)
输出示例:
🧪 v2.0.1 修复验证测试套件(14/14)+ v2.1.0 回归(16/16)+ v2.2.0 知识库(10+)
📊 全量: 40+ passed, 零缓存残留(.pyc/__pycache__ 会话前后双清理)