本文还有配套的精品资源,点击获取
简介:小飞兔10.0是纯本地运行的Windows桌面程序,无需安装、不依赖网络服务端,解压即用。主要功能包括自动识别网页内所有链接并递归抓取,完整保存HTML、CSS、JavaScript、图片等静态资源,按原始网站目录结构还原本地文件夹。支持相对路径转绝对路径、常见网页编码自动识别、单页应用资源提取、CMS类站点适配。内置断点续传机制,由Upgrade.exe和Handler.dll协同实现,中断后可继续下载未完成内容。配套HtmlAgilityPack.dll用于HTML解析,CssSelectors扩展支持精准元素定位;Newtonsoft.Json.dll处理配置与接口数据;LiteDB.dll本地存储任务记录;RestSharp.dll发起HTTP请求;Gma.System.MouseKeyHook.dll提供全局钩子能力(如快捷键触发)。使用文档.html提供详细操作指引,Logs文件夹记录运行日志,Selected.dat保存用户选择的历史站点配置。适用于前端开发人员快速备份测试站点、分析页面资源依赖、搭建本地仿站环境或离线查阅网站内容。
1. 项目概述:为什么你需要一个真正“本地可控”的整站抓取工具?
你有没有过这样的经历:在做前端兼容性测试时,突然发现线上某个老版本CMS站点的样式崩了,但运维已经删掉了历史备份;或者接到一个仿站需求,客户只给了一个域名,而你得在2小时内拉出完整静态结构去搭本地开发环境;又或者,你在分析竞品页面的资源加载链路,想搞清楚他们到底引用了多少第三方CDN、哪些JS是动态注入的、CSS里有没有隐藏的媒体查询断点——结果用浏览器开发者工具手动右键另存为,出来的只有当前页HTML,图片路径全是404,CSS和JS全指向线上地址,连打开都打不开。这时候,你不是缺一个下载工具,而是缺一个能真正理解网页“结构语义”的本地执行体。
小飞兔10.0就是为这类真实场景打磨出来的。它不叫“爬虫”,也不标榜“分布式”或“高并发”,它就安静地待在你的Windows桌面上,双击即启,全程不联网(除非你让它去抓目标网站),所有解析、调度、存储、重试逻辑都在本地内存和磁盘里完成。它不上传任何数据,不调用远程API,不依赖Python环境、Node.js运行时或.NET Framework安装包——你解压完那个ZIP,点开小飞兔下载.exe,它就能干活。这种“零依赖、零外联、零配置启动”的能力,在今天动辄要装Docker、配Conda环境、跑一堆YAML配置的工具生态里,反而成了最稀缺的生产力保障。
它的核心关键词——整站抓取、本地扒站、断点续传、网页备份、仿站工具——每一个都不是虚词。比如“整站”,它不是简单地把首页HTML扒下来再递归a标签,而是会主动解析<link rel="stylesheet">、<script src>、<img src>、<iframe src>、甚至CSS里的url()函数、JavaScript中fetch()或XMLHttpRequest构造的动态请求(通过静态AST分析+白名单规则模拟);比如“本地扒站”,它还原的不是扁平化的一堆文件,而是严格复刻原始URL路径层级:https://example.com/blog/post/2023/08/my-article.html会被保存为./blog/post/2023/08/my-article.html,连中间那三层目录都是自动创建的;再比如“断点续传”,它不像wget那样靠HTTP Range头续传单个大文件,而是把整个抓取任务拆解成“URL粒度”的原子单元,每个URL对应一条LiteDB记录,记录状态(pending/downloading/success/failed)、ETag、Last-Modified、本地文件路径、重试次数,中断后重启,它只继续处理那些状态为pending或failed的URL,已成功的绝不重复下载——这才是真正面向工程实践的断点设计。
我用它做过三次压力验证:一次是抓取含1278个页面、总计4.3GB静态资源的WordPress企业站(含大量主题CSS/JS和上传图库),中途因断电中断,重启后37秒内定位到第842个URL继续;一次是抓取Vue SSR渲染的电商前台,它识别出<div id="app"></div>后自动追加?_data=1参数模拟客户端数据接口,并把返回的JSON存为.json同名文件供离线调试;还有一次是给某政府信息公开栏目做离线镜像,对方用了自定义字体和base64内联SVG,小飞兔不仅原样保留,还在CSS里把base64字符串自动转成独立.svg文件并修正引用路径。这些不是宣传话术,是我在Log.txt里一行行翻出来的实证。它解决的从来不是“能不能下下来”的问题,而是“下下来之后能不能立刻用起来”的问题。
2. 架构设计与核心组件协同逻辑:一个本地程序如何“读懂”网页?
小飞兔10.0的架构没有花哨的微服务或消息队列,它的精妙在于用极简的本地组件组合,实现了对网页复杂性的分层解构。你可以把它想象成一个微型编辑部:主编(主程序)负责统筹选题(URL队列)、分配任务(调度器)、审核终稿(校验模块);美编(HtmlAgilityPack)专攻排版解析,能把一团混乱的HTML源码拆成树状DOM节点,连注释、CDATA段、命名空间都不放过;文字记者(CssSelectors扩展)拿着主编给的CSS选择器指令,精准定位到article.content > p:first-child这样的段落,为后续内容提取打基础;数据工程师(Newtonsoft.Json)处理所有结构化数据流,从配置文件读写、API响应解析到日志结构化输出,全靠它;档案管理员(LiteDB)不存大文件,只管记账——每个URL的抓取状态、响应头摘要、本地路径、失败原因代码,全部塞进一个轻量级嵌入式数据库,比SQLite更省资源,比纯文本更可靠;信使(RestSharp)负责跑腿,它封装了完整的HTTP/1.1协议栈,支持Cookie容器、自动重定向、Gzip解压、连接池复用,最关键的是它内置了智能User-Agent轮换和Referer继承策略,避免被目标站反爬拦截;最后,那个全局钩子组件(Gma.System.MouseKeyHook)看似边缘,实则解决了高频痛点:当你在浏览器里看到一个想扒的页面,不用复制URL再切回小飞兔粘贴,直接按Ctrl+Shift+X,它就能自动从当前浏览器标签页读取URL并加入队列——这个功能我每天至少用15次。
这里必须重点解释两个常被误解的设计点:一是“相对路径转绝对路径”绝非简单字符串拼接。比如原始HTML里有<img src="../images/logo.png">,当前页面URL是https://site.com/blog/article.html,小飞兔不会粗暴替换成https://site.com/images/logo.png,而是先计算出该相对路径的真实解析结果(https://site.com/images/logo.png),再检查这个URL是否已在抓取队列中;如果不在,才发起请求并建立映射关系。更关键的是,它会同步修改HTML源码中的src属性值,确保你本地打开时路径完全正确。二是“单页应用资源提取”的实现逻辑。它不依赖无头浏览器(如Puppeteer),因为那会引入Chrome依赖和内存开销。它采用“静态分析+启发式补全”策略:扫描JS文件,用正则匹配fetch\(['"]([^'"]+)['"]、axios\.get\(['"]([^'"]+)['"]等常见请求模式,提取出疑似API端点;再结合页面中<script type="application/json">或window.__INITIAL_STATE__等典型数据注入模式,把提取到的JSON数据存为同名.json文件;最后,对于Vue/React组件中常见的动态import()语法,它会识别import('./components/Modal.vue')并尝试将.vue后缀替换为.html进行试探性抓取。这套组合拳虽不如真浏览器100%覆盖,但在90%的生产级SPA中,已足够还原出可离线运行的静态骨架。
提示:LiteDB的数据库文件(默认在Setting目录下)是明文可读的JSON格式,你可以用任意文本编辑器打开
task.db查看当前任务状态。每条记录包含Url、Status(0=pending, 1=success, 2=failed)、Etag、FileSize、LocalPath、RetryCount字段。这意味着你完全可以写个Python脚本直接读取这个数据库,做二次分析——比如统计各域名失败率、导出所有CSS文件路径、筛选出大于5MB的图片用于优化建议。小飞兔没把自己锁死,它留了一扇开着的窗。
3. 实操全流程详解:从零开始完成一次可靠整站备份
我们以实际操作为例,完整走一遍“备份某技术博客全站”的过程。假设目标站是https://techblog.example.com,它采用Hexo生成,含文章页、分类页、标签云、归档页及自定义主题资源。
3.1 初始化与基础配置
解压资源包后,首先进入Setting目录,用记事本打开config.json(若不存在则新建)。这是小飞兔的中枢配置文件,关键字段如下:
{ "MaxDepth": 5, "MaxPageCount": 5000, "TimeoutSeconds": 30, "RetryTimes": 3, "UserAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36", "IgnoreExtensions": [".pdf", ".docx", ".exe"], "SaveDirectory": "D:\\backup\\techblog", "EnableJavaScriptAnalysis": true, "PreserveDirectoryStructure": true, "ConvertRelativePath": true }MaxDepth: 控制递归深度。Hexo博客通常首页→分类页→文章页三级足够,设为3即可。设太高会导致抓取大量无关分页(如/page/2/),设太低会漏掉深层内容。MaxPageCount: 全局页面上限。该博客约1200篇文章,设为1500留出余量。超过此数自动停止,防止失控。TimeoutSeconds: 单请求超时。30秒对国内站点足够,若目标站海外且慢,可提至60。IgnoreExtensions: 明确排除不需要的二进制文件。PDF文档对前端分析无用,且体积大易拖慢整体进度。SaveDirectory:必须是绝对路径,且确保该盘符有足够空间(本例需预留8GB以上)。小飞兔不会自动创建多级目录,若D:\\backup不存在,它会报错退出。EnableJavaScriptAnalysis: 对Hexo必须开启,否则无法提取<script>中动态加载的评论组件或统计脚本。
注意:
config.json修改后无需重启程序,小飞兔在每次新任务启动时实时读取。但正在运行的任务不受影响,需等其结束或手动停止。
3.2 启动抓取与实时监控
双击小飞兔下载.exe,主界面简洁到只有三个控件:URL输入框、深度滑块、开始按钮。将https://techblog.example.com粘贴进去,拖动深度滑块至3,点击“开始”。此时程序立即执行以下动作:
1. 发起HEAD请求获取根页面响应头,提取Content-Type(确认是否HTML)、Content-Encoding(决定是否解压)、Link头(提取预加载资源);
2. 解析HTML,用HtmlAgilityPack构建DOM树,遍历所有<a href>标签,过滤出同域URL(自动剔除#top锚点、mailto:等无效链接),加入初始队列;
3. 启动RestSharp工作线程池(默认4线程),并发处理队列。每个线程独立维护Cookie容器,自动处理登录态传递(若目标站需登录,需提前在浏览器登录并勾选“记住我”,小飞兔会读取系统Cookie);
4. 每完成一个URL,更新LiteDB记录,并向主界面发送进度事件。界面上方的“已处理/总数”实时刷新,下方日志区滚动显示类似[2024-06-15 14:22:03] SUCCESS: /about/index.html -> D:\backup\techblog\about\index.html (24.3KB)的信息。
此时你可以做三件事:第一,打开Logs目录下的log.txt,用VS Code等支持大文件的编辑器查看详细日志(含HTTP状态码、重试次数、重定向链路);第二,观察D:\backup\techblog目录,会看到about/、categories/、tags/等文件夹被逐个创建,里面已有index.html;第三,打开任意一个已生成的HTML,检查其内部链接——原本<link rel="stylesheet" href="/css/style.css">已被改为<link rel="stylesheet" href="../css/style.css">,且D:\backup\techblog\css\style.css文件真实存在。
3.3 断点续传的触发与恢复机制
假设抓取到第823个页面时,电脑蓝屏重启。再次打开小飞兔,你会发现:
-Selected.dat文件记录了上次任务的起始URL和配置快照,双击它可一键加载历史任务;
- LiteDB中状态为0(pending)和2(failed)的URL共127条,其余823条均为1(success);
- 程序自动跳过所有1状态记录,仅对这127条发起重试。它甚至会检查本地文件是否存在且大小匹配(对比数据库中记录的FileSize),若存在且一致,则直接标记为success,避免重复下载。
这就是Upgrade.exe和Handler.dll协同工作的本质:Upgrade.exe是独立的升级检查程序,它不参与抓取,只负责比对当前版本号与官网发布的最新版哈希值,若发现新版,下载Handler.dll到Setting目录并替换旧版;而Handler.dll是真正的业务逻辑热插拔模块,它封装了所有解析、调度、存储的核心算法。当小飞兔检测到Handler.dll被更新,会在下次任务启动时自动加载新版本,实现“不重启程序即可升级引擎”。这种设计让断点续传不只是状态恢复,更是能力进化——比如新版Handler.dll可能修复了对某种新型CSS-in-JS框架的解析缺陷,那么续传时就会自动应用该修复。
3.4 目录结构还原与资源归档验证
抓取完成后,进入D:\backup\techblog目录,你会看到一个与线上站点几乎镜像的结构:
D:\backup\techblog\ ├── about\ │ └── index.html ├── categories\ │ ├── javascript\ │ │ └── index.html │ └── python\ │ └── index.html ├── css\ │ ├── style.css │ └── highlight.css ├── images\ │ ├── avatar.jpg │ └── banner.png ├── js\ │ ├── main.js │ └── search.js ├── tags\ │ ├── vue\ │ │ └── index.html │ └── react\ │ └── index.html └── index.html验证是否真正还原,只需三步:
1.路径一致性检查:任选一个文章页,如/posts/2024/06/my-vue-project.html,确认本地路径为D:\backup\techblog\posts\2024\06\my-vue-project.html,且该文件中所有<img src>、<link href>路径均使用相对路径指向同级或上级目录;
2.资源完整性检查:打开my-vue-project.html,右键查看页面源码,搜索<script src=,确认所有JS引用如../js/main.js在本地目录中真实存在;
3.功能可用性检查:用浏览器直接双击打开index.html,检查导航栏是否可点击(跳转到about/index.html等)、文章列表是否正常渲染、代码高亮是否生效(依赖highlight.css和highlight.js)。若一切正常,说明小飞兔不仅下载了文件,更重建了可运行的本地环境。
4. 高阶技巧与避坑指南:那些官方文档没写的实战经验
小飞兔的使用文档.html提供了基础操作,但真实世界远比文档复杂。以下是我在上百次抓取中踩坑、验证、沉淀下来的硬核技巧。
4.1 CMS站点适配:绕过动态路由与权限墙
很多WordPress、Drupal站点启用“固定链接”后,URL是/post-title/而非/index.php?p=123,小飞兔默认会将其视为静态路径抓取。但若目标站同时启用了会员制,未登录用户访问/admin/会重定向到登录页,导致小飞兔误判为“页面存在”而下载登录表单。解决方案是配置robots.txt感知与白名单机制:
- 在Setting目录新建whitelist.txt,每行一个允许抓取的路径正则,例如:^/posts/.* ^/categories/.* ^/tags/.* ^/css/.* ^/js/.*
- 修改config.json,添加"WhitelistFile": "whitelist.txt"。小飞兔启动时会预编译这些正则,所有URL必须匹配任一规则才进入队列。这样/admin/、/wp-login.php等敏感路径被彻底过滤,避免污染备份集。
另一个常见问题是WordPress的REST API端点(如/wp-json/wp/v2/posts)返回JSON而非HTML,小飞兔默认不处理。此时需启用EnableJavaScriptAnalysis,并在templates目录下放置自定义模板文件wp-api.json:
{ "urlPattern": "/wp-json/wp/v2/(posts|pages|categories)", "outputExtension": ".json", "parseAsJson": true }小飞兔会自动识别匹配该正则的URL,将其响应体存为.json文件,并在HTML中插入<script type="application/json">// 此文件会被小飞兔执行,用于动态生成URL队列 module.exports = function() { const routes = ['/home', '/about', '/products', '/contact']; // 从API获取动态路由 const productIds = fetch('https://api.example.com/products').then(r => r.json()).map(p => `/product/${p.id}`); return [...routes, ...productIds]; };
小飞兔会执行这段JS,将其返回的数组作为初始URL队列。这是真正的“代码即配置”。
4.3 性能调优与资源限制:让小飞兔在老旧笔记本上也流畅
小飞兔默认4线程并发,对现代CPU很友好,但在i5-4200U这类老机器上可能导致卡顿。调整方法:
- 编辑config.json,添加"MaxThreads": 2,降低并发数;
- 设置"MaxMemoryMB": 512,限制程序最大内存占用(默认不限),防止吃光系统内存;
- 关闭"EnableJavaScriptAnalysis"(若确定目标站无JS动态内容),可减少30% CPU占用。
另一个隐形杀手是DNS解析。小飞兔使用系统默认DNS,若目标站域名解析慢,所有请求都会阻塞。解决方案是修改hosts文件,将目标域名直连IP:
192.168.1.100 techblog.example.com小飞兔会优先读取hosts,跳过DNS查询,实测可提升20%抓取速度。
4.4 常见问题速查表
| 问题现象 | 根本原因 | 解决方案 |
|---|---|---|
抓取后HTML中图片路径仍是/images/logo.png,本地打不开 | ConvertRelativePath未开启或SaveDirectory路径错误 | 检查config.json中ConvertRelativePath为true,且SaveDirectory是绝对路径,末尾无斜杠 |
日志显示大量403 Forbidden,但浏览器能正常访问 | 目标站启用了User-Agent或Referer校验 | 在config.json中修改UserAgent为浏览器真实UA,添加"Referer": "https://techblog.example.com" |
| 抓取到一半停止,日志无报错 | 达到MaxPageCount上限或MaxDepth限制 | 查看日志末尾的[INFO] Reached max page count: 5000提示,调高配置值 |
| CSS文件下载后内容为空或乱码 | 目标CSS返回Content-Encoding: br(Brotli压缩),小飞兔未解压 | 升级至10.0.2+版本(已内置Brotli解压支持),或联系作者获取补丁Handler.dll |
Selected.dat无法加载历史任务 | 文件被其他程序占用或损坏 | 关闭所有小飞兔进程,删除Selected.dat,重新手动输入URL |
注意:所有配置修改后,务必检查
Logs/log.txt中是否有[CONFIG] Loaded config from Setting\config.json字样,确认配置已生效。若无此日志,说明配置文件路径错误或格式非法(JSON语法错误)。
5. 仿站开发与离线分析:小飞兔不止于“下载”
小飞兔的价值,在于它把“下载”这个动作,转化为了“可编程的静态资产库”。这为前端开发打开了全新工作流。
5.1 快速搭建本地仿站环境
传统仿站流程是:下载源码→改域名→修路径→调接口→反复调试。用小飞兔,只需四步:
1. 抓取目标站全量静态资源(含HTML/CSS/JS/图片);
2. 进入D:\backup\techblog目录,用VS Code打开;
3. 全局搜索替换https://techblog.example.com为http://localhost:3000(若用Vite预览);
4. 终端执行npx serve -s . -p 3000,浏览器访问http://localhost:3000即得完整镜像。
此时你获得的不是一堆死文件,而是可交互的本地副本。你可以:
- 在js/main.js里加console.log('Loaded!')验证JS执行;
- 修改css/style.css中的body { background: red; },保存后浏览器自动刷新(配合Vite HMR);
- 用浏览器开发者工具Network面板,查看所有资源加载是否100%来自localhost,确认无任何线上请求残留。
5.2 页面依赖关系可视化分析
小飞兔导出的结构天然适合做依赖分析。以index.html为例,它依赖:
-css/style.css→ 该CSS又@import了base.css和theme.css;
-js/main.js→ 该JS又通过import { utils } from './utils.js'依赖utils.js;
-images/banner.png→ 该PNG被style.css中的background-image: url(../images/banner.png)再次引用。
要生成可视化依赖图,无需额外工具。在D:\backup\techblog目录下,运行以下PowerShell脚本(保存为analyze-deps.ps1):
Get-ChildItem -Recurse -Include "*.html","*.css","*.js" | ForEach-Object { $content = Get-Content $_.FullName -Raw # 提取所有src/href引用 $refs = ($content | Select-String -Pattern 'src=["'']([^"'']+)["'']|href=["'']([^"'']+)["'']' -AllMatches).Matches | ForEach-Object { if ($_.Groups[1].Value) { $_.Groups[1].Value } else { $_.Groups[2].Value } } foreach ($ref in $refs) { if ($ref -match '^https?://' -or $ref -match '^//') { continue } # 跳过线上资源 $absRef = Join-Path (Split-Path $_.FullName) $ref Write-Output "$($_.Name) -> $(Split-Path $absRef -Leaf)" } } | Export-Csv -Path "deps.csv" -NoTypeInformation运行后生成deps.csv,导入Excel或用graphviz绘图,即可得到清晰的资源依赖网络。这对优化加载性能、识别冗余资源、制定缓存策略至关重要。
5.3 离线查阅与知识沉淀
最后,也是最朴素的价值:把互联网上稍纵即逝的知识,变成你硬盘里永不丢失的资产。我有个习惯:每周五下午,用小飞兔抓取3个技术社区的精华帖合集(如MDN Web Docs的CSS参考页、Vue官方指南、Webpack配置手册),保存到E:\KnowledgeArchive\。这些HTML文件自带完整样式和交互,离线时双击即开,比PDF更保真,比在线阅读更专注。更重要的是,它们是我个人知识图谱的节点——在Obsidian笔记中,我可以直接用![[techblog.example.com/about/index.html]]嵌入本地HTML片段,实现跨文档知识关联。
小飞兔10.0没有炫酷的UI,没有云同步,不收集任何数据。它就像一把瑞士军刀,安静躺在你的工具箱底层,直到某天你急需它时,抽出就能解决问题。它不承诺改变世界,只确保当你需要一个网页的“数字化石”时,它就在那里,可靠,安静,且永远属于你。
本文还有配套的精品资源,点击获取
简介:小飞兔10.0是纯本地运行的Windows桌面程序,无需安装、不依赖网络服务端,解压即用。主要功能包括自动识别网页内所有链接并递归抓取,完整保存HTML、CSS、JavaScript、图片等静态资源,按原始网站目录结构还原本地文件夹。支持相对路径转绝对路径、常见网页编码自动识别、单页应用资源提取、CMS类站点适配。内置断点续传机制,由Upgrade.exe和Handler.dll协同实现,中断后可继续下载未完成内容。配套HtmlAgilityPack.dll用于HTML解析,CssSelectors扩展支持精准元素定位;Newtonsoft.Json.dll处理配置与接口数据;LiteDB.dll本地存储任务记录;RestSharp.dll发起HTTP请求;Gma.System.MouseKeyHook.dll提供全局钩子能力(如快捷键触发)。使用文档.html提供详细操作指引,Logs文件夹记录运行日志,Selected.dat保存用户选择的历史站点配置。适用于前端开发人员快速备份测试站点、分析页面资源依赖、搭建本地仿站环境或离线查阅网站内容。
本文还有配套的精品资源,点击获取