网站离线复刻 · 整站抓成可编辑离线副本

SKILL开发
开发 未标注权限 许可证不明确
安装这个技能

把任意在线网站抓成本地副本——双击即开、完全断网可用、源码保持原样可编辑。五步流程:渲染后枚举链接(静态 HTML 扫不到的 JS 生成导航)→ 整站下载并把绝对路径改写成相对路径 → JS 内硬编码资源 URL 本地化 → CDP 拦死所有 http(s) 做断网验收 → 与在线页逐像素量化还原度。同时覆盖三个工程硬骨头:hash 路由的同页 hash 去重陷阱、跨域资源落兄弟目录导致重跑不可幂等(产物落 _mirror_state.json,重跑跳过 → 副作用是手工修改不被覆盖)、注入浏览器代码的反斜杠二次转义。当用户说"把整个网站抓下来离线""整站镜像""网站离线复刻""离线后还要能改""断网能打开""扒站""做个离线副本""这个网站我想存到本地方便改"时使用。不触发:只想看单页正文(用 WebFetch)、需要 WARC/WACZ 归档还原(另用 wacz-to-editable-html)、只想找历史快照(用 Wayback)。

一句话选型结论

按资料字段整理

网站离线复刻 · 整站抓成可编辑离线副本是开发类的 Agent Skill,安装方式未标注,权限级别未标注,许可证不明确,有可直接复制的安装命令。技能本质是给模型读的说明书,效果取决于模型与客户端;装完先用一个小任务验证,再放进正式流程。

分类开发 安装方式未标注 权限级别未标注权限 许可证许可证不明确
累计安装 未标注 本周 未标注
GitHub 星标 未标注 仓库 未标注
下载量 未标注 技能市场下载数
权限级别 未标注权限 安装前请确认风险范围
许可证 许可证不明确 未说明

安装

未标注
在支持 Skills 的客户端里执行,装完问一句「你有哪些技能」验证
skillhub install user_0c7f1934/website-offline-mirror
  1. 1
    确认客户端支持

    确认你的客户端支持 Skills(Claude、Codex、Cursor 等),并升级到较新的版本。

  2. 2
    拿到技能文件

    执行上面的命令安装;也可以把仓库里的 SKILL.md 手动放进客户端的 skills 目录。

  3. 3
    刷新技能列表

    重新打开客户端,或刷新技能列表,让新放进来的技能被加载。

  4. 4
    验证是否生效

    问一句「你有哪些技能」,确认列表里出现它,再拿一个小任务试跑。

技能档案

开发
字段来自技能仓库与公开索引,中文说明由本站标注
作者 / 维护方user_0c7f1934仓库 未标注 · 版本 未标注
宿主客户端未标注技能可被这些客户端加载
安装方式未标注安装包 community
权限级别未标注权限安装前请确认风险范围
许可证未说明许可证不明确,商用前请自行确认条款
仓库可用性available技能仓库当前是否可访问
最近核验2026-11-06上游最后核验时间 · 数据更新 2026-11-06
正文体量14.2 KBSKILL.md 原文大小,越大说明说明书写得越细

典型使用场景

3 类
按分类整理的常见用法,具体以 SKILL.md 为准
写代码与改 bug

按需求补代码、定位并修掉报错。

读仓库与生成改动

让模型读懂项目结构,再给出可落地的改动。

跑测试与排查故障

按现象排查问题,补测试用例并复跑。

选择建议

装之前先看这几条
按条目字段给出的判断,不替你决定用不用

值得选的地方

  • 有可直接复制的安装命令,不用自己翻文档找入口。

先想清楚的地方

  • 没有标注权限级别,实际能做什么要装好后确认。
  • 许可证不明确,商用或二次分发前先到仓库确认条款。
  • 没有做站内核验,内容以作者仓库为准。
  • 技能只是说明书,实际效果取决于模型与客户端,装完先用小任务试一遍。

更适合

  • 需要在开发场景里给模型补一套做法的人。
  • 愿意先读一遍 SKILL.md、确认它会让模型做什么的人。

不太适合

  • 对许可证要求很严、必须明确可商用的人。
  • 只想装完就自动变强、不打算看说明书的人。

同类对比

6 个同类
同分类里挑最接近的几条,字段以各自详情页为准
技能权限级别安装方式累计安装宿主客户端安装命令
网站离线复刻 · 整站抓成可编辑离线副本当前 未标注权限 未标注 未标注 未标注 有
技能审查员 浏览器控制 ClawHub 市场 877.9 万 OpenClaw 有
Vercel React 最佳实践 浏览器控制 GitHub 仓库 849.1 万 Codex、Claude、Cursor 有
GitHub 代码协作 联网访问 ClawHub 市场 763.3 万 OpenClaw 有
网页设计指南 联网访问 GitHub 仓库 668.6 万 Codex、Claude、Cursor 有
本体论 只读 ClawHub 市场 663.7 万 OpenClaw 有

SKILL.md 全文

14.2 KB
模型实际读到的说明书原文,来自技能仓库

网站离线复刻 · 整站镜像

环境准备

pip install -r requirements.txt

依赖:numpy、Pillow(用于生成缩略图与资源处理)。


把一个在线网站抓成本地副本:双击即开、完全断网可用、源码原样可编辑。

> 现场实测基线(xueai.miyang.cn/slides/learn.html,466 节课的课程站):
> 634 文件 / 30.77 MB / 112 秒抓完;重跑 0.1 秒跳过 492 个文件且产物指纹不变(幂等 PASS);
> 7 个页面断网验收全部 0 外链 PASS;与在线页逐像素比对平均差 0.57(阈值 <6 为良好)。

触发条件

触发方式 示例
关键词 "把整个网站抓下来离线"、"整站镜像"、"网站离线复刻"、"离线后还要能改"、"断网能打开"、"扒站"、"做个离线副本"
场景 用户给出一个在线站点 URL,要求本地可打开且可编辑

不触发:只读单页正文 → WebFetch;有 .warc/.wacz 归档要还原 → wacz-to-editable-html;只想找历史快照 → Wayback。

适用边界(重要)

本技能面向静态 / 服务端渲染(SSR)站点:页面由 HTML + 服务端吐出的链接构成,或经无头浏览器渲染后 DOM 里能枚举出 &lt;a href&gt; 导航与框架运行时数据(Next 的 __NEXT_DATA__、Nuxt 的 __NUXT__、Redux 初始态、window.COURSE/__DATA__ 等,discover_links.mjs 已自动探测)。

> ⚠ 纯客户端 SPA 的边界:若站点所有页面内容都靠前端 JS 动态生成、且既不暴露上述 window 数据源、也不渲染出可点击的 &lt;a href&gt; 导航(例如入口只有一个空 #app 容器、路由完全由 JS 接管且无锚点),则本流程无法可靠抓全页面。此类"纯客户端渲染 SPA"请改用 site-clone-static(走 API 抓取 + mock 后端)来复刻,不要强行用本技能"承诺能抓任意网站"。
>
> 实践上:先跑 ① discover_links.mjs,看 PAGES 数量是否覆盖预期页面;若 PAGES 明显过少(远少于站点真实页面数),基本可判定为纯客户端 SPA,转 site-clone-static。


一、五步流程(顺序不可换)

① 渲染后枚举  →  ② 整站下载改写  →  ③ JS 资源收尾  →  ④ 断网验收  →  ⑤ 还原度量化
步 命令 在解决什么
① node scripts/discover_links.mjs --url &lt;入口&gt; --out urls.txt --wait 9000 --same-origin-only 静态 HTML 里看不到 JS 生成的导航,必须渲染后再枚举
② python scripts/offline_mirror.py --entry &lt;入口&gt; --urls-file urls.txt --out &lt;目录&gt; --threads 12 下载全部依赖 + 绝对路径改写成相对路径
③ (②自动执行,--no-rewrite-js 可关) JS 里硬编码的资源 URL,扫 src= 扫不到
④ node scripts/verify_offline.mjs --url &quot;file:///&lt;绝对路径&gt;/&lt;目录&gt;/&lt;host&gt;/&lt;path&gt;&quot; --out 断网.png CDP 拦死所有 http(s),证明零外链
⑤ python scripts/verify.py 在线.png 断网.png --profile --heat diff.png 把"像不像"变成数字

为什么是这个顺序:①不先做,②就会漏掉整片页面(实测站静态 HTML 里只有 8 个链接,
渲染后是 959 个);④不做,你无法区分"看起来对"和"真的不联网"。

环境要求

  • Python 3.9+(offline_mirror.py 只用标准库;verify.py 需 Pillow + numpy)
  • Node 18+(用了内置 fetch / WebSocket,无需 npm install)
  • 本机装了 Edge 或 Chrome(④①靠 CDP 驱动;也可 --exe 或 BROWSER_EXE 环境变量指定)

从零复现(可直接粘)

SK=&lt;本技能目录&gt;
PY=&lt;python&gt;
NODE=&lt;node&gt;

# 1) 渲染后枚举链接
$NODE &quot;$SK/scripts/discover_links.mjs&quot; \
    --url &quot;https://example.com/slides/learn.html&quot; \
    --out urls.txt --wait 9000 --same-origin-only

# 2) 整站镜像(下载 + 路径改写 + JS 资源本地化 + 状态清单 + 审计报告)
$PY &quot;$SK/scripts/offline_mirror.py&quot; \
    --entry &quot;https://example.com/slides/learn.html&quot; \
    --urls-file urls.txt --out ./离线副本 --threads 12

# 3) 断网验收
$NODE &quot;$SK/scripts/verify_offline.mjs&quot; \
    --url &quot;file:///D:/离线副本/example.com/slides/learn.html&quot; \
    --out 断网.png

# 4) 还原度量化(需 Pillow + numpy)
$PY &quot;$SK/scripts/verify.py&quot; 在线.png 断网.png --profile --heat diff.png

关于入口:--entry 必须给真实存在的路径。若用户给的 URL 带 hash(...#lesson-9.html),
先确认该 hash 解析出的页面真实存在——很多站查不到就静默回退到首页,
你以为在复刻 A,其实复刻的是 B(本次实测就踩了:learn-223.html 根本不存在,
站点回退到 roadmap.html)。


二、六个坑(都实测踩过,不是理论)

1. JS 生成的导航,静态扫描扫不到

learn.html 的 466 节目录是 buildTree() 用 window.COURSE 渲染的,静态扫 &lt;a href&gt; 只拿到 8 条。

解法:CDP 渲染 → 收集 a/iframe/link/script/img/srcset → 再递归遍历运行时数据源。
递归深度要给够——课程树是 parts → topics → lessons → item 四层嵌套,
深度限制成 4 时 lessons 那层正好够不着,一个都收不到。

2. hash 路由:同页 hash 会被"去重"吃掉

全站链接都是 learn.html#roadmap.html 这种形式,pathname 完全相同。
抹掉 hash 再做 URL 去重,466 条会塌成 1 条。

解法:同页 hash 链接保留 hash 参与去重。另外补一条通用启发式——
hash 形如 #xxx.html 时,把 xxx.html 当真实路径再试一次(相对当前页目录解析)。
纯锚点 #section-2 不带扩展名,不会误报。

3. 跨域资源落在"兄弟目录",导致改写不可重复施加

本地布局是 out/&lt;host&gt;/&lt;path&gt;。跨域资源(img.alice.miyang.cn/...)成了 out/ 下的
兄弟目录,相对路径必须"爬出"主机目录:../../img.alice.miyang.cn/...。
这种路径再喂一次 urljoin 会被解析成 xueai.miyang.cn/img.alice.miyang.cn/... → 404。

后果:重跑一次,产物就坏一次(实测指纹从 0963beab 变成 aca1b09d,多出 22 个假 404)。

解法:产物是给人改的,所以重跑必须原样跳过已处理文件。工具落一份
&lt;out&gt;/_mirror_state.json,重跑 0.1 秒跳过 492 个文件。
副作用正好是想要的:你对副本做的手工修改,重跑不会覆盖(要强制重抓用 --force)。

4. data URI 内层的 url(%23n)

background-image:url(&quot;data:image/svg+xml,...&lt;rect ... filter=&#x27;url(%23n)&#x27;/&gt;...&quot;)

外层 url(data:…) 被正确跳过,但正则继续往后扫,撞上内层的 url(%23n)——
于是工具跑去抓一个根本不存在的 /slides/%23n。

解法:%23 是百分号编码的 #,把它和 # 一起列入"不下载前缀"。

5. 注入浏览器的代码,反斜杠要二次转义

discover_links.mjs 的采集代码是字符串形式塞进 Runtime.evaluate 的。
写成 JS 模板字符串时,[\w\-.%] 会被吃掉反斜杠变成 [w-.%] →
运行时 SyntaxError: Range out of order in character class。

教训:往浏览器注入的代码里,每一个反斜杠都要按字符串层再转义一次。
写完必须真跑一次——静态看不出来(这次就是这么发现的)。

6. JS 里硬编码的资源 URL

bar.innerHTML = &#x27;&lt;img src=&quot;https://img.alice.miyang.cn/xueai/qrcode.jpg&quot; alt=&quot;QR&quot;&gt;&#x27;

HTML 里没有这个引用,扫 src= 扫不到。

解法:下载完成后做第二遍,用"已成功镜像"的清单反查 JS/内联脚本里的绝对 URL,
命中就换成本地相对路径(实测站 1411 处 / 473 个文件)。
只处理无 query 无 fragment 的 URL——带 query 的多是运行时拼接,静态替换必错。


三、验收标准(必须两个都做)

断网验收 —— 判定 PASS/FAIL

verify_offline.mjs 用 CDP 把 http://* / https://* 全部拦死,只放行 file://。
这比"拔网线"更严格也更好用:不依赖当前机器网络状态,结果可复现,且每个漏网的资源
都会被打上 URL + 类型。

判定       PASS  ← 零外链,完全离线

还原度量化 —— 判定 良好/可接受

指标 良好 可接受
平均绝对差 < 6 < 12
中位差 < 2 < 5
>32 像素占比 < 3% < 8%

> 对比前必须让两边处于同一状态。 在线页常默认开着登录面板 / AI 侧栏,会挤压正文宽度。
> 实测:直接比得到 18.27 的假差异;用 --block alice 把在线页的侧栏请求也拦掉后降到 0.57。
> 用 --block &lt;关键词&gt; 可拦任意一类 URL,--allow-net 进入"在线对照模式"(不做离线判定)。

残余差异怎么归因:本次留下的只有三个小方块,全部是数据来源差异、不是复刻错误——
顶栏进度计数(在线走 /auth/progress 同步,离线只有 localStorage)、水印编号、二维码区。
--heat diff.png 出热力图,一眼看出差异是"结构错"还是"数据不同"。


四、不能自动化的部分(要如实告诉使用者)

类别 例子 处理
服务端功能 登录、全文搜索、进度云同步、AI 侧栏 离线不可用;页面有兜底,一般不崩
运行时拼接的远程 URL img.src=&#x27;https://cdn/badge?style=1&amp;dark=&#x27;+(dark?&#x27;true&#x27;:&#x27;false&#x27;) 工具会报告出来,人工一行改掉即可
跨域 iframe 的脚本访问 file:// 下 origin 是 null,frame.contentDocument 拿不到 页面照常显示,只是外壳脚本改不了 iframe 内部

最后一条的解法:要恢复同源能力,用本地 HTTP 服务打开即可——

python -m http.server 8080 --directory 离线副本
# 访问 http://127.0.0.1:8080/&lt;host&gt;/&lt;path&gt;

五、为什么产物是"可编辑"的

  1. 不打包、不混淆、不反编译 —— 输出就是原站源码,HTML/CSS/JS 原样保留。
  2. 按 URL 目录结构落盘 —— &lt;out&gt;/&lt;域名&gt;/&lt;路径&gt;,一眼知道每个文件对应哪个页面。
  3. 重跑不覆盖修改 —— _mirror_state.json 记录已处理清单(见坑 3)。
  4. 改动有据可查 —— 工具改写(相对路径化、CDN 本地化)与手工修改混在一起,但
    _report.json 记录每一处失败及其来源文件,能溯源到"哪个文件哪条引用"。

六、工具清单

文件 作用
scripts/discover_links.mjs 渲染后枚举同源链接;--eval 可跑任意通用探针;--json 出结构化结果
scripts/offline_mirror.py 整站镜像:下载、路径改写、JS 资源本地化、状态清单、审计报告(纯标准库)
scripts/verify_offline.mjs 断网验收:CDP 拦死 http(s),报告外链 / JS 异常 / 控制台错误 / 截图
scripts/verify.py 逐像素还原度比对(需 Pillow + numpy);--profile --heat --crop --dy-scan

关键参数速查

# discover_links.mjs
--url &lt;URL&gt;  --out &lt;文件&gt;  --wait &lt;ms&gt;  --same-origin-only
--eval &quot;&lt;JS表达式&gt;&quot;   # 通用探针,输出 JSON,用来摸清页面结构
--exe &lt;浏览器路径&gt;    # 找不到浏览器时指定

# offline_mirror.py
--entry &lt;URL&gt;(可多次)  --urls-file &lt;清单&gt;  --out &lt;目录&gt;
--threads 12            # 并发
--force                 # 忽略状态清单,强制重抓(会覆盖手工修改!)
--no-cross              # 不下载跨域资源
--no-rewrite-js         # 关闭 JS 资源本地化
--follow-pages          # 顺带抓同源 &lt;a href&gt; 页面

# verify_offline.mjs
--url &lt;file:///...&gt;  --out &lt;png&gt;  --w 1600 --h 1000 --wait 9000
--eval &quot;&lt;JS&gt;&quot;      # 截图前注入(如关弹窗),配 --post-delay 2500 等动画走完
--allow-net        # 在线对照模式
--block &lt;关键词&gt;   # 额外拦掉匹配的 URL,做可比对照

七、交付物清单(给用户看什么)

  1. 副本入口页 &lt;out&gt;/_打开这里.html(双击即开)
  2. 断网验收截图 + 判定(PASS/FAIL)
  3. 还原度数字(平均差 / 中位差 / >32 占比)+ 热力图
  4. 工具会写 &lt;out&gt;/_report.json:成功/失败、外链残留(区分资源型与内容型)、
    每个失败的来源文件

版本历史

  • v1.0.0 (2026-09-27) — 首次发布。从 xueai.miyang.cn 实测中提炼:五步流程、
    六个坑(JS 导航 / hash 去重 / 跨域兄弟目录导致不可幂等 / data URI 内层 url() /
    注入代码反斜杠 / JS 硬编码资源 URL)、断网 + 逐像素双层验收、可编辑性保障。

常见问题

5 问
答案由本站依据条目字段整理
网站离线复刻 · 整站抓成可编辑离线副本怎么安装?

在支持 Skills 的客户端里执行:skillhub install user_0c7f1934/website-offline-mirror。安装方式为未标注。装完刷新技能列表或重开客户端。

网站离线复刻 · 整站抓成可编辑离线副本支持哪些客户端?

资料没有标注宿主客户端,但只要客户端支持 Skills(Claude、Codex、Cursor 等),一般都能加载。

网站离线复刻 · 整站抓成可编辑离线副本权限高吗,安全吗?

权限级别为未标注权限。安装前先看它会读取或写入哪些内容。

网站离线复刻 · 整站抓成可编辑离线副本收费吗?

本站不代收费用,也没有标注具体价格。是否收费取决于技能本身和所用的模型或客户端,正式使用前按作者说明确认。

网站离线复刻 · 整站抓成可编辑离线副本用什么许可证?

许可证标注为 未说明(许可证不明确)。商用或二次分发前请到仓库确认条款原文。

热门专题

按场景挑技能
全部专题 →

技能内容以作者仓库为准;分类、权限级别与许可证状态的中文说明为中文整理,最近核验 2026-11-06。