TypeScript小说下载器:构建可扩展架构的数字内容保存方案
【免费下载链接】novel-downloader一个可扩展的通用型小说下载器。项目地址: https://gitcode.com/gh_mirrors/no/novel-downloader
🎬 数字阅读时代的架构挑战
在当前的网络环境中,数字内容的脆弱性已成为技术社区必须面对的挑战。小说网站的结构多样性、内容呈现方式的不断变化,以及平台可能随时关闭的现实,构成了一个复杂的数字内容保存难题。我们开发的novel-downloader项目,正是对这一挑战的技术回应——一个基于TypeScript构建的、具备高度可扩展性的小说下载解决方案。
作为一款油猴脚本,novel-downloader直接在浏览器环境中运行,避免了传统爬虫工具需要配置代理、处理Cookie等复杂操作。其核心设计理念是:通过模块化的规则系统,实现对100+小说网站的智能适配,同时保持代码的清晰结构和易于维护的特性。
novel-downloader的后台运行状态展示,通过开发者工具监控网络请求和下载进度
🔧 模块化架构深度解析
核心模块设计
项目采用清晰的分层架构,每个模块承担特定职责:
src/ ├── main/ # 核心数据模型:Book、Chapter、Attachment ├── rules/ # 网站解析规则,按网站类型分类组织 ├── lib/ # 工具库和辅助函数 ├── save/ # 多格式输出引擎 └── ui/ # 用户界面组件Book类(src/main/Book.ts)作为核心数据容器,管理小说的元数据、章节列表和保存配置。每个Book实例包含完整的作品信息,支持通过saveOptions进行自定义输出配置。
Chapter类(src/main/Chapter.ts)封装了章节的解析逻辑,包括内容提取、图片处理和状态管理。这种设计使得每个章节可以独立处理,支持并行下载和错误重试机制。
规则系统的技术实现
规则系统是novel-downloader的核心创新。在src/rules/目录下,我们按照网站类型建立了多层级的规则组织:
// 基础规则类示例 export abstract class BaseRuleClass { abstract bookParse(): Promise<Book>; abstract chapterParse(): Promise<ChapterParseObject>; // 通用DOM解析方法 protected async cleanDOM(element: HTMLElement): Promise<CleanResult> { // 清理HTML,提取纯文本和图片 } }每种网站类型都有对应的规则实现:
- onePage/:单页式网站,所有章节在同一页面
- twoPage/:分页式网站,章节内容分布在多个页面
- special/:特殊网站,需要额外处理逻辑(如字体加密、图片文字等)
多格式输出引擎
src/save/模块实现了多种输出格式的支持:
- TXT格式:纯文本输出,适合快速阅读和文本处理
- EPUB格式:标准电子书格式,支持目录导航和图文混排
- RAW格式:原始HTML保存,保留网站原始结构
每种格式都有独立的处理逻辑,通过模板引擎(Jinja2)生成最终文件。这种设计使得添加新的输出格式变得简单直观。
novel-downloader提取的小说正文内容,格式清晰,保留了原始排版结构
💡 技术实现细节与扩展机制
DOM解析与内容提取
项目采用渐进式的DOM解析策略,首先通过CSS选择器定位内容区域,然后应用cleanDOM函数清理无关元素:
// src/lib/cleanDOM.ts的核心逻辑 export async function cleanDOM( element: HTMLElement, mode: "TM" | "normal" ): Promise<CleanResult> { // 移除广告、导航、评论等无关元素 // 提取纯文本内容 // 收集图片资源 // 应用用户自定义的清理规则 }对于复杂的网站结构,我们实现了nextPageParse函数,支持自动翻页和内容合并。这在处理分页式网站时尤为重要。
图片文字处理的三层解码方案
面对使用图片代替文字的网站(如西瓜书屋),我们实现了三级解码策略:
- 文件名映射:通过图片文件名直接匹配文字,速度最快
- 哈希匹配:计算图片哈希值进行匹配,平衡速度与准确性
- OCR识别:使用PaddleOCR进行光学字符识别,准确性最高但速度较慢
// src/lib/decoders/ImageCache.ts中的实现 export class ImageCache { async decode(imageUrl: string): Promise<string> { // 尝试文件名映射 const filenameMatch = this.filenameMapping.get(imageUrl); if (filenameMatch) return filenameMatch; // 尝试哈希匹配 const hash = await this.calculateHash(imageUrl); const hashMatch = this.hashMapping.get(hash); if (hashMatch) return hashMatch; // 最后使用OCR return await this.ocrDecode(imageUrl); } }字体加密处理
对于使用字体加密的网站(如晋江文学城),我们实现了自动字体映射系统。当检测到加密字体时,系统会:
- 下载字体文件并解析字形映射
- 建立Unicode到实际字符的映射表
- 应用映射表替换加密字符
novel-downloader处理含图片小说的效果,图片与文字完美整合
📊 扩展开发指南
添加新网站支持
要为新的小说网站添加支持,开发者只需创建新的规则文件并实现几个关键方法:
- 创建规则文件:在适当的
src/rules/子目录中创建新的TypeScript文件 - 实现BaseRuleClass:继承基础类并实现
bookParse和chapterParse方法 - 注册路由:在
src/router/download.ts中添加网站匹配规则 - 更新配置文件:在
header.json的match字段添加URL模式
// 示例:简单的单页式网站规则 export class ExampleRule extends BaseRuleClass { public constructor() { super(); this.imageMode = "TM"; this.charset = "utf-8"; } async bookParse(): Promise<Book> { // 解析书籍基本信息 const doc = await getHtmlDOM(this.bookUrl, this.charset); const bookname = doc.querySelector("h1").textContent.trim(); const author = doc.querySelector(".author").textContent.trim(); return new Book({ bookUrl: this.bookUrl, bookname, author, // ... 其他参数 }); } async chapterParse(): Promise<ChapterParseObject> { // 解析章节内容 const doc = await getHtmlDOM(this.chapterUrl, this.charset); const content = doc.querySelector(".content") as HTMLElement; return await cleanDOM(content, "TM"); } }调试与测试
项目提供了完善的调试工具:
- 调试模式:在设置中启用后,生成详细的
debug.log文件 - 测试视图:可视化界面显示解析结果和错误信息
- 控制台日志:通过F12开发者工具查看实时运行状态
novel-downloader解析的小说目录页面,自动识别章节结构和元数据
⚡ 高级配置与自定义
自定义下载参数
通过window.saveOptions对象,用户可以完全控制输出格式:
// 自定义章节标题格式 const saveOptions = { getchapterName: (chapter) => { return `第${chapter.chapterNumber}章 ${chapter.chapterName || ''}`; }, // 自定义CSS样式 mainStyleText: `p { text-indent: 2em; line-height: 1.6; }`, // 章节排序规则 chapterSort: (a, b) => a.chapterNumber - b.chapterNumber };章节筛选功能
用户可以定义chapterFilter函数来选择性下载章节:
// 只下载前50章 function chapterFilter(chapter) { return chapter.chapterNumber <= 50; } // 只下载特定卷的内容 function chapterFilter(chapter) { return chapter.sectionName === "第一卷"; }性能优化配置
针对不同网站的反爬机制,可以调整下载参数:
// 在设置面板中调整 { parallelThreads: 3, // 并行下载线程数 downloadInterval: 1000, // 下载间隔(毫秒) maxInterval: 5000 // 最大间隔时间 }🛠️ 构建与部署
本地开发环境搭建
# 克隆项目 git clone https://gitcode.com/gh_mirrors/no/novel-downloader cd novel-downloader # 安装依赖 yarn install # 开发构建 yarn build # 生产构建 yarn build:production构建完成后,在dist/目录中会生成bundle.user.js文件,可以直接安装到油猴脚本管理器中。
持续集成与测试
项目使用TypeScript进行类型检查,确保代码质量:
# 类型检查 yarn type-check # 代码格式化 yarn format # 运行测试 yarn testnovel-downloader处理的长文本内容,保留了完整的角色对话和世界观设定
🔍 技术价值与社会意义
开源协作模式
novel-downloader采用AGPL-3.0许可证,鼓励社区贡献。项目的模块化设计使得添加新网站支持变得简单,开发者可以专注于特定网站的解析逻辑,而无需理解整个系统的复杂性。
我们建立了清晰的贡献流程:
- 在GitHub上提交issue描述需求
- 创建对应的规则文件
- 提交Pull Request
- 经过代码审查后合并
数字文化遗产保存
项目的核心价值超越了单纯的技术工具。在"404时代",许多优秀的网络文学作品因各种原因从互联网上消失。novel-downloader不仅是一个下载工具,更是数字文化遗产保存的技术方案。
通过集成互联网档案馆(archive.org)的存档功能,对于无登录墙的小说网站,脚本可以自动将书籍详情页和目录页存档,为后人保留访问这些作品的机会。
技术栈选择的意义
选择TypeScript作为开发语言具有多重优势:
- 类型安全:减少运行时错误,提高代码可靠性
- 更好的开发体验:智能提示和代码补全
- 易于维护:清晰的接口定义和类型约束
- 社区生态:丰富的类型定义和工具链支持
油猴脚本的运行环境选择也体现了技术权衡:
- 无需安装:直接在浏览器中运行
- 跨平台:支持所有主流浏览器
- 权限控制:明确的权限声明,用户可控
- 自动更新:通过脚本管理器自动获取新版本
📈 未来发展方向
技术路线图
- 性能优化:进一步优化图片处理和OCR识别速度
- 规则自动化:探索基于机器学习的网站结构自动识别
- 格式扩展:支持更多电子书格式(如MOBI、PDF)
- 云同步:集成云存储服务,实现多设备同步
社区生态建设
我们计划建立更完善的开发者文档和示例,包括:
- 详细的规则开发教程
- 常见问题解决方案
- 性能优化指南
- 贡献者指南
🎯 开始使用
对于终端用户,安装过程简单直接:
- 安装油猴脚本管理器(Tampermonkey、Violentmonkey等)
- 访问项目页面获取最新脚本
- 访问支持的小说网站,点击右上角下载图标
对于开发者,项目提供了完整的开发环境:
- 克隆项目并安装依赖
- 研究现有规则实现
- 为新网站创建规则文件
- 提交Pull Request贡献代码
novel-downloader代表了我们对数字内容保存的技术思考和实践。通过模块化设计、类型安全和社区协作,我们构建了一个既强大又灵活的工具,帮助读者保存他们珍视的数字内容,同时也为开源社区贡献了一个高质量的技术解决方案。
在技术不断演进的时代,这样的工具不仅解决了实际问题,更体现了开源精神的价值——通过代码共享和技术协作,共同应对数字时代的挑战。
【免费下载链接】novel-downloader一个可扩展的通用型小说下载器。项目地址: https://gitcode.com/gh_mirrors/no/novel-downloader
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考