---
name: spa-scrape
version: 1.0.0
description: |
  将 SPA（单页应用）网站完整扒下来，生成纯静态 HTML 文件。
  适用于 Vue/React/Angular 等前端框架渲染的网站。
  触发词："扒站"、"扒下来"、"抓取这个网站"、"spa scrape"、"静态化这个网站"。
allowed-tools:
  - Bash
  - Read
  - Write
  - Edit
  - Grep
  - Glob
  - Agent
  - AskUserQuestion
  - mcp__playwright__browser_navigate
  - mcp__playwright__browser_snapshot
  - mcp__playwright__browser_evaluate
  - mcp__playwright__browser_click
  - mcp__playwright__browser_network_requests
  - mcp__playwright__browser_network_request
  - mcp__playwright__browser_take_screenshot
  - mcp__playwright__browser_wait_for
  - mcp__playwright__browser_run_code_unsafe
triggers:
  - 扒站
  - 扒下来
  - 把网站扒下来
  - 抓取这个网站
  - spa scrape
  - 静态化这个网站
  - 整站下载
---

# SPA 网站扒站工具

将动态渲染的 SPA 网站（Vue/React/Angular）转换为纯静态 HTML 文件，保留布局和样式。

## 完整工作流程

### 阶段 1：探索网站结构

1. **打开目标网站**
   ```
   browser_navigate → 目标 URL
   browser_wait_for → 等待 3-5 秒让 SPA 渲染完成
   ```

2. **获取路由表**（关键步骤）
   ```
   browser_evaluate → 执行 JS 获取 Vue Router / React Router 路由表
   ```
   - Vue: `document.querySelector('#app').__vue_app__._instance.appContext.config.globalProperties.$router.options.routes`
   - React: 查 Network 面板或遍历 DOM 导航链接
   - 通用: `browser_snapshot` 获取页面结构，提取所有导航链接

3. **发现静态资源**
   ```
   browser_network_requests → static=true → 列出所有 JS/CSS/图片/字体
   ```
   记录带 hash 的文件名（如 `index-Cwp7s7md.js`、`a1-BKC9nY_U.png`）

4. **触发懒加载**
   ```
   逐一点击导航链接 → browser_click → browser_wait_for → browser_network_requests
   ```
   发现微前端子应用、路由懒加载 chunk

### 阶段 2：下载资源

5. **创建本地目录结构**
   ```bash
   mkdir -p <output-dir>/{assets,子应用目录...}
   ```

6. **下载入口 HTML**
   ```bash
   curl -sL -o <output-dir>/index.html <网站URL>
   ```

7. **批量下载静态资源**
   ```bash
   # 下载 JS/CSS
   curl -sL -o <output-dir>/assets/xxx.js <网站URL>/assets/xxx.js
   # 下载图片（带 hash 的文件名）
   curl -sL -o <output-dir>/assets/a1-XXX.png <网站URL>/assets/a1-XXX.png
   # 下载字体
   curl -sL -o <output-dir>/assets/iconfont-XXX.woff2 <网站URL>/assets/iconfont-XXX.woff2
   ```
   **并行下载**: 用多个 subagent 同时下载不同目录的资源

### 阶段 3：捕获页面快照

8. **逐个页面捕获渲染后的 HTML**
   ```
   browser_navigate → 页面路由
   browser_wait_for → 3 秒等待渲染
   browser_evaluate → document.documentElement.outerHTML → 保存为 .html
   ```
   **并行处理**: 用 subagent 同时抓取多个页面

### 阶段 4：清洗 HTML

9. **去掉不需要的内容**
   ```python
   import re
   # 去掉所有 <script> 标签
   html = re.sub(r'<script[^>]*>.*?</script>', '', html, flags=re.DOTALL)
   # 去掉外部 JS 引用（保留模板语法如 {{ }}）
   # 去掉 <link rel="modulepreload">
   html = re.sub(r'<link[^>]*modulepreload[^>]*>', '', html)
   ```

10. **修复资源路径**
    ```python
    # 添加 <base> 标签让图片等资源从远程加载
    html = html.replace('<head>', '<head><base href="https://原网站域名/">')
    # 修复相对路径
    html = re.sub(r'url\(\./iconfont-', 'url(assets/iconfont-', html)
    html = re.sub(r'url\(\./(?!assets/)', 'url(https://原网站域名/', html)
    # 修复 CSS 中的 CORS 字体
    html = html.replace("url(./", "url(assets/")
    ```

11. **修复渲染问题**
    ```python
    # SVG 转义
    html = html.replace('=\\"', '="')
    # 注入缺失的 Header/公共组件样式
    # （某些页面依赖公共组件 CSS，需要手动注入）
    ```

### 阶段 5：验证

12. **本地预览**
    ```bash
    # 启动简单 HTTP 服务器
    cd <output-dir> && python3 -m http.server 8899
    ```
    然后在浏览器中逐个打开页面，检查：
    - 布局是否正常
    - 图片是否加载
    - 字体图标是否显示
    - 浏览器 Console 是否有 404/CORS 错误

13. **修复问题**
    - CORS 错误 → 检查 `base` 标签和资源路径
    - 图片 404 → 检查 hash 文件名是否正确
    - 样式缺失 → 注入缺失的 CSS
    - 布局错乱 → 检查 CSS 文件是否完整下载

## 常见陷阱

| 问题 | 原因 | 解决 |
|------|------|------|
| 图片 hash 错误 | 不同构建版本的 hash 不同 | 从 Network 面板确认当前 hash |
| CORS 字体加载失败 | `url()` 路径不对 | 改为本地路径或完整 URL |
| Header/导航样式缺失 | 微前端公共组件 CSS 未注入 | 手动注入 common-components CSS |
| SVG 图标显示异常 | Vue 渲染的 `=\"` 转义 | `replace('=\\"', '="')` |
| 页面跳转到登录 | Keycloak/OAuth 认证拦截 | 单独下载登录页，或跳过需要认证的路由 |
| 滚动触发路由切换 | SPA 的 scroll-to-anchor | 小心使用 browser_evaluate，避免触发滚动 |

## 输出物

```
<output-dir>/
├── index.html                    # 主入口
├── standalone-homepage.html      # 首页完整快照（可直接浏览器打开）
├── all-styles.css                # 所有 CSS 合并文件
├── screenshot-fullpage.png       # 首页截图
├── <page1>.html                  # 各页面快照
├── <page2>.html
├── ...
├── assets/                       # 静态资源
│   ├── *.js
│   ├── *.css
│   ├── *.png / *.jpg
│   ├── *.woff2 / *.ttf
│   └── *.mp4
└── <子应用>/                     # 微前端子应用资源
    └── ...
```

## 使用示例

```
用户: 把 https://example.com/#/ 这个网站扒下来
用户: spa-scrape https://example.com
用户: 静态化这个 Vue 网站
```
