
前言
在日常开发和学习中,我们经常需要将某个网页完整保存下来用于离线参考、模板学习或网站备份。虽然市面上有 HTTrack、SiteSucker 等桌面工具,但它们需要安装,使用门槛较高。
于是,我用 PHP 开发了这个 SiteGrab 网站整站下载器,部署到服务器后即可通过浏览器一键使用,无需安装任何软件。
在线体验: (部署后填入你的域名)
功能特性
| 功能 | 说明 |
|---|---|
| 全资源抓取 | 自动提取 HTML、CSS、JS、图片、字体、视频等全部资源,递归解析 CSS 中的子引用(如 @import、url()) |
| 路径自动修正 | 下载后自动将远程绝对路径替换为本地相对路径,解压后双击 index.html 即可离线浏览 |
| 编码自动转换 | 自动检测 GBK、GB2312、UTF-8 等编码,统一转为 UTF-8,告别乱码 |
| ZIP 打包下载 | 全部资源打包为 ZIP 压缩包,保留完整目录结构,以域名为文件名方便管理 |
| 实时进度反馈 | 基于 SSE(Server-Sent Events)实时推送抓取日志和进度,体验流畅 |
| 灵活配置 | 支持同域限制、CSS 解析开关、JS 下载开关、抓取深度(0-3层)、超时时间等参数调节 |
技术栈
- 后端: PHP 7.4+(cURL 扩展、ZipArchive 扩展)
- 前端: 原生 HTML/CSS/JavaScript,无任何外部依赖
- 通信: Server-Sent Events(SSE)实现实时进度推送
- UI: 现代化响应式设计,支持桌面和移动端
项目结构
sitegrab/ ├── index.php # 前端页面(含完整 HTML/CSS/JS)├── download.php├── cleanup.php # 后端抓取逻辑(SSE 接口) └── downloads/ # 临时文件目录(自动创建,存放 ZIP 文件)
部署方法
环境要求
- PHP >= 7.4
- cURL 扩展(
php_curl) - ZipArchive 扩展(
php_zip) - 支持 Apache / Nginx / 宝塔面板
安装步骤
将
index.php和download.php上传到网站根目录或子目录确保 PHP 已启用
curl和zip扩展(宝塔面板可在 PHP 管理 → 安装扩展中开启)确保目录有写入权限(用于生成临时 ZIP 文件):
chmod 755 ./访问
http://你 的域名/即可使用
Nginx 伪静态(可选)
如果使用 Nginx,确保 SSE 长连接不受缓冲影响:
location ~ \.php$ {
proxy_buffering off;
fastcgi_buffering off;
# ... 其他 fastcgi 配置
}使用说明
- 在输入框填写目标网站地址(需包含
http://或https://) - 根据需要调整选项:
- 仅同域:只下载目标域名下的资源,跳过第三方 CDN 和统计代码,减小压缩包体积
- 解析 CSS:递归解析 CSS 文件中的
@import和url()引用 - 下载 JS:下载页面引用的 JavaScript 文件
- 抓取深度:0=仅当前页资源,1=含CSS子资源,2=进一步递归,3=最深层递归
- 超时时间:单个资源请求的超时时间
- 点击「开始下载」按钮,等待资源抓取完成
- 完成后点击「下载 ZIP 压缩包」保存到本地
- 解压 ZIP 文件,双击
index.html即可离线浏览
核心代码解析
SSE 实时通信
前端通过 EventSource 接收后端推送的实时日志和进度:
evtSource = new EventSource('download.php?' + params.toString());
// 监听日志事件
evtSource.addEventListener('log', function(e) {
var data = JSON.parse(e.data);
log(data.msg, data.t || '');
});
// 监听进度事件
evtSource.addEventListener('progress', function(e) {
var data = JSON.parse(e.data);
// 更新进度条和计数
});
// 监听完成事件
evtSource.addEventListener('done', function(e) {
var data = JSON.parse(e.data);
// 显示下载链接
});后端 SSE 输出格式
后端通过标准 SSE 格式向前端推送消息:
// 日志消息
echo "event: log\ndata: " . json_encode(['msg' => '正在抓取...', 't' => 'info']) . "\n\n";
// 进度更新
echo "event: progress\ndata: " . json_encode(['total' => 100, 'done' => 50]) . "\n\n";
// 完成通知
echo "event: done\ndata: " . json_encode(['zip_url' => '/tmp/xxx.zip', 'size' => '2.5MB']) . "\n\n";
ob_flush();
flush();CSS 子资源递归解析
程序会自动解析 CSS 文件中的资源引用:
// 匹配 url() 引用
preg_match_all('/url$["\']?([^"\')\s]+)["\']?$/i', $cssContent, $matches);
// 匹配 @import 引用
preg_match_all('/@import\s+["\']([^"\']+)["\']/', $cssContent, $imports);编码自动检测
// 检测编码
$encoding = mb_detect_encoding($content, ['UTF-8', 'GBK', 'GB2312', 'BIG5'], true);
// 转换为 UTF-8
if ($encoding && $encoding !== 'UTF-8') {
$content = mb_convert_encoding($content, 'UTF-8', $encoding);
}界面预览
界面采用现代化设计风格,主要特点:
- 渐变蓝色主题,视觉清爽
- 卡片式布局,信息层次分明
- 深色终端风格日志区域,专业感十足
- 响应式设计,完美适配手机和桌面端
- 无任何外部 CSS/JS 依赖,加载速度极快
常见问题
Q:下载后网页打不开或样式错乱? A:请确保先解压再打开 index.html,不要在 ZIP 内直接预览。部分使用 CDN 绝对路径的资源可能仍需联网。
Q:为什么有些图片没下载? A:图片可能通过 JS 动态加载(懒加载),勾选「下载JS」并增大抓取深度可覆盖更多资源。
Q:支持哪些网站? A:支持所有公开可访问的网站。需登录或有反爬机制的站点可能无法完整抓取。
Q:抓取深度怎么选? A:一般选 2 即可满足需求。0=仅当前页资源;1=含CSS子资源;2=进一步递归。
注意事项
- 部分网站有防盗链或动态加载机制,可能无法完整抓取
- 本工具仅供合法用途,请勿用于侵犯他人版权
- 建议部署在有足够磁盘空间和带宽的服务器上
- 定期清理 download 目录中的临时文件
开源协议
本项目采用 MIT 协议开源,欢迎自由使用和二次开发。
联系作者
- 作者:KUS
- QQ:2762264258
💬 评论 (0)