简介:整站下载工具资源包以Teleport Pro为核心,面向需要离线访问网站、整站镜像备份或研究网站抓取机制的用户,特别适合对批量保存页面、图片、样式与脚本有明确需求的技术爱好者。压缩包共10个文件,约553KB,兼顾轻量与实用:exe程序可直接运行,PDF手册提供完整操作指引,HTM帮助页面辅助查阅界面功能,txt文档覆盖使用、汉化与项目说明,tpp文件则为现成项目示例。已有185人学习下载,适合个人学习、资料归档或小型站点备份场景。通过该包可获得可用的整站下载工具与配套学习材料,理解URL解析、递归下载、资源提取、重定向处理、登录状态保持及本地文件组织等关键流程,还可参照内置项目示例快速上手;同时需谨记尊重网站版权,确保在授权范围内使用。
1. 整站下载与网站复制:从“复制文件夹”到“资源工程”
整站下载这个词,听起来像把一个文件夹复制到本地,但真正操作过的人都知道,它其实是一项资源工程:HTML、CSS、JS、图片、字体、JSON 接口、乃至登录态,每一类资源都可能单独出问题。一个典型的翻车现场是——抓下来打开 index.html,页面能渲染,图片全裂,样式全丢,点哪个链接都是 404。所以这篇笔记会把整站下载与网站复制的完整链路拆开讲清楚:从抓取工具选型、wget 参数组合、链接改写策略,到带登录态的抓取、接口数据归档和完整性验证,每一步都给出可以直接复现的命令和踩坑记录。适合做站点归档、离线镜像、线上迁移或本地预览的前端、运维和测试从业者。
2. 抓取链路先想清楚:工具选型、参数组合与增量同步机制
真正动手下载一个站点前,最忌讳的是拿到工具就狂点“开始”。整站抓取的本质,是把一个网站的服务端资源集合变成一份本地可浏览的文件集合,这个过程中有三个环节最容易变形:递归深度、资源携带范围、链接改写规则。先把工具选型和各自的边界说透,再谈命令,后面才不会被各种玄学问题拖着走。
2.1 三条主流路线的边界:什么时候用 wget,什么时候换 HTTrack
整站下载的工具不少,但真正能进生产流程的也就那么几条路线。我把实际用过的方案整理成一张对比表,方便按场景选型。
| 方案 | 工作方式 | 擅长场景 | 边界与常见问题 |
|---|---|---|---|
| wget | 命令行递归抓取 | Linux/服务器批量归档、脚本化增量同步 | 对 JS 动态渲染页面无效,参数设置不当容易外扩抓取 |
| HTTrack | 图形化镜像工具 | Windows 桌面操作、交互式配置、一次性镜像 | 自动化程度低,路径改写规则有时过于粗暴,难嵌入流水线 |
| 浏览器扩展 | 在浏览器内保存页面 | 单页保存、携带登录态的小规模下载 | 不做全站递归,不处理深层链接,大站基本用不上 |
从实际场景看,这三类需求最常见:站点归档(把线上内容完整保存下来)、迁移测试(复制一份到本地做改版预览)、离线展示(内网环境无法访问外网时提供浏览能力)。wget 对前两者最合适,因为它能脚本化、能增量同步、能精确控制资源范围;HTTrack 适合习惯图形界面的 Windows 用户;浏览器扩展只适合临时存一两个页面,想靠它完整复制一个几百页的站点,基本是给自己找麻烦。
选型还有一个关键判断:目标站点是静态渲染还是动态渲染。所谓静态渲染,就是服务端把 HTML 拼好返回,浏览器拿到就能展示;动态渲染则是指页面结构靠 JS 在浏览器里生成,服务端返回的 HTML 只是一个空壳。wget 对前者几乎完美,对后者只能抓到空壳。判断方法在第 3 章会展开,这里先记住结论:动手之前先 curl 一下首页源码,看目标 HTML 里是不是有实际内容,这一步能省掉后面大量返工。
2.2 一条能直接跑的 wget 整站命令:每个参数都拆开讲
以一份内部文档站为例,完整抓取命令我一般这样写:
wget \ --mirror \ --page-requisites \ --adjust-extension \ --convert-links \ --restrict-file-names=windows \ --domains docs.example.com,static.example.com \ --span-hosts \ --no-parent \ --wait=2 \ --random-wait \ --user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36" \ --directory-prefix=./site_backup \ https://docs.example.com/先解释最核心的几个。--mirror是镜像模式的开关,等价于同时开启递归、时间戳比对和无限层级,它保证了第一次全量抓取后,后续同步时能按文件时间差做增量,而不是从头再抓一遍。--page-requisites会把页面依赖的 CSS、JS、图片、字体一并下载,整站复制时这个参数必须带,否则得到的只是一个“纯 HTML 骨架”。--adjust-extension会把没有扩展名的动态 URL 补上 .html,比如/article?id=123存成本地文件时自动变成.html,方便本地双击打开。--convert-links是抓完后的链接改写开关,wget 会自动把页面里的绝对地址改写成相对地址,这一步决定你复制出来的站能不能离线浏览,但它有盲区,第 3 章专门讲。
然后是防出错的关键参数。--restrict-file-names=windows表示文件名严格按 Windows 兼容规则处理,把?、&、:等非法字符替换成下划线。别以为只有 Windows 需要,在 Linux 上打包转交给别人时经常会传到 Windows 环境,提前限制能避免解压后一堆文件名非法。--domains指定允许抓取的域名白名单,多个域名用逗号分隔;--span-hosts则允许跨域抓取。这两个参数必须要配合使用:只开--span-hosts不限制域名,会把页面里引用的所有外站资源全部拉回来;只限--domains不开--span-hosts,则静态资源如果放在独立 CDN 域名下就会全部漏抓。--no-parent阻止向目标 URL 的上级目录递归,防止把整台服务器能访问到的内容都拖下来。
防反爬相关的参数同样重要。--wait=2表示每次请求之间至少间隔 2 秒,--random-wait会在 0.5 到 2 倍的间隔之间随机波动,模拟人工浏览节奏,避免因为请求频率太高被服务端限流。--user-agent把请求 UA 伪装成常规浏览器,不少站点会拦截无 UA 或明显是爬虫的请求。最后--directory-prefix指定本地保存根目录,抓下来的文件会按域名建目录,./site_backup/docs.example.com/就是站点根目录。
2.3 增量续传与定时同步:让镜像站持续跟上源站
如果你的诉求不是一次性抓完,而是每周、每天和源站保持同步,那就要把上面的命令包成一个脚本,配合增量参数做定时任务。
#!/bin/bash SITE=https://docs.example.com DEST=/data/backup/docs_site wget --mirror --page-requisites --adjust-extension \ --convert-links --restrict-file-names=windows \ --domains docs.example.com,static.example.com \ --span-hosts --no-parent --wait=2 --random-wait \ --directory-prefix="$DEST" "$SITE"这段脚本的核心是--mirror,它内置了-N时间戳比对逻辑:本地文件时间戳比源站新,就跳过;比源站旧,就重新下载。配合 Linux 的 crontab 就能形成自动同步链路,比如每天凌晨三点执行:
0 3 * * * /opt/scripts/wget_sync.sh >> /var/log/wget_sync.log 2>&1这里有一个资深用户才会踩到的坑:部分服务器响应头里不带 Last-Modified,或者服务器时钟严重不准,导致--mirror每次都觉得本地文件“过期”,增量同步变成全量重抓。解决方法是给 wget 加上--no-use-server-timestamps,让本地文件时间戳不被服务器响应头覆盖,之后比对就始终以第一次抓取的本地时间为准。代价是源站后续更新不会被自动发现,所以这个参数更适合源站内容基本稳定、只需要补漏的场景。首次全量抓取建议先手动跑一遍,同时开着日志观察,确认没有大面积 403 或超时后再交给 cron。
3. 路径改写与资源本地化:抓完打不开才是第一道坎
很多同学第一次做整站下载,wget 跑完看到几万个文件,觉得大功告成,双击 index.html 却看到一堆裂图和白板。问题几乎都出在链接改写和资源本地化上。这一章把--convert-links的能力边界、手动改写的时机、以及动态渲染站点的识别与处理讲清楚。
3.1 --convert-links 做了什么,又漏掉了什么
--convert-links的工作机制是:wget 抓完所有资源后,会遍历下载下来的 HTML 和 CSS,把其中指向源站 URL 的 href、src、url() 改写成指向本地文件的相对路径,同时保留一份原始文件,后缀是.orig。比如源站页面里有一个<a href="https://docs.example.com/guide/start">,改写后会变成<a href="guide/start.html">。当你打包这些文件时,.orig文件应该被排除掉,它们只是改写的备份,留着会让目录体积翻倍且没有任何运行时价值。
但--convert-links的覆盖范围远没有想象中广。它只处理 wget 在抓取阶段“认识”的链接,也就是说,只有 HTML 源码里直接写死的 href、src 才会被改写。以下几个场景它完全管不着:
第一种是 JavaScript 里动态拼接的 URL,比如代码里写const api = '/api/v1/data',然后 fetch 请求,这种路径在 HTML 里不存在,wget 也看不到,改不了。第二种是懒加载图片的>grep -rhoE 'https?://[a-zA-Z0-9.\-]+' ./site_backup --include="*.html" --include="*.css" \ | sort | uniq -c | sort -rn
这条命令递归提取 HTML 和 CSS 里所有 HTTP/HTTPS 链接的域名部分,按出现次数排序。输出结果里出现次数最多的域名,就是当前页面里最主要的资源来源。如果它已经在--domains白名单里且资源已抓取,只是链接没改写,那么直接用 sed 把源站域名替换成根相对路径即可,注意用|作为分隔符避免和路径里的/冲突:
find ./site_backup -type f \( -name "*.html" -o -name "*.css" \) \ -exec sed -i 's|https://docs\.example\.com/|/|g' {} +这条命令会把 HTML 和 CSS 里硬编码的源站绝对路径改写成根相对路径。改完以后页面里的/guide/start.html会直接落在本地站点根目录下。但这里有一条必须遵守的纪律:不要对第三方 CDN 域名做同样的替换。比如站点用到了阿里云 OSS 上的图片,你本地并没有这些图片,强行把https://cdn.oss.example.com/改成/,结果就是所有图片从“远程加载失败”变成“本地不存在的资源 404”,比不改还糟。正确的做法是:源站域名改成根相对路径,CDN 域名保持原样,让离线预览时仍能访问公开 CDN 的资源。
sed 批量改写前,我强烈建议先备份目录,哪怕只是cp -r site_backup site_backup.bak。改写出错不会立刻暴露,往往是浏览到第三四个页面才发现问题,如果没有备份,后悔药都没得吃。
3.3 动态渲染站点:抓下来只有空壳怎么识别与处理
wget 递归抓取对 SPA 站点基本是无效的,但很多人是在抓完以后才意识到这点。判断方法很简单,抓之前先用 curl 看目标 URL 返回的 HTML 里是否真的有页面内容:
curl -sL https://app.example.com/ | grep -oE '<div[^>]*id="(root|app)"[^>]*>'如果输出结果里能匹配到id="root"或id="app"这样的节点,而且节点内部没有任何实际文本内容,那这基本就是一个 React/Vue 单页应用,服务端返回的只是空壳。此时 wget 抓下来的 HTML 文件数量可能很多,但每个文件都只有几十到几百字节,没有任何正文。
应对这类站点有两个路线。第一个是放弃抓 HTML,直接抓页面背后调用的 JSON 接口,用接口数据重建内容,这适合内容型站点,第 6 章会展开讲接口归档方法。第二个是用无头浏览器渲染后再抓取,具体做法是让浏览器加载页面、执行完 JS、把渲染后的完整 DOM 保存成静态 HTML,这条路能拿到真实内容,代价是每个页面都要等渲染完成,抓几千个页面的耗时和资源消耗都很大,更适合小规模高价值页面。
另一个容易被忽略的方向是站点提供 sitemap.xml。很多动态站点服务端渲染能力很差,但 sitemap 是完整且准确的 URL 清单,把 sitemap 里的链接作为种子 URL 喂给 wget,可以绕过爬虫递归不到链接的问题:
curl -s https://app.example.com/sitemap.xml | grep -oE '<loc>[^<]+</loc>' | sed 's/<\/\?loc>//g' > /tmp/urls.txt wget --input-file=/tmp/urls.txt --force-html --page-requisites --convert-links --directory-prefix=./spa_backup这样抓到的是每个 URL 的服务端响应内容。如果响应里包含完整内容,这个方案可行;如果响应依旧是空壳,那必须在抓取环节就引入无头浏览器,后续第 6 章讨论的接口直连归档会是更务实的替代方案。
4. 整站复制避坑指南:五个高频翻车现场与排查顺序
这一章记录的是过去几年我在做整站抓取时遇到的高频问题,每一条都是真实翻车经历,按“现象 → 原因 → 解决”的方式写。如果你抓完的站点有问题,优先对照这几条排查。
4.1 只抓到首页没有子页面
现象:本地备份里只有一个 index.html,没有子目录,HTML 文件总数是个位数,整个站点看起来就像一个空壳。
原因有三个。第一,wget 默认遵守 robots.txt,如果站点在 robots 协议里禁止了子路径爬取,wget 会主动跳过。第二,--level参数默认值是 5,如果站点链接层级深,很多子页面在第 5 层之下就抓不到了。第三,站点页面里的导航链接是 JS 动态生成的,wget 的解析器根本看不到这些链接,递归就此中断。
解决:如果目标站授权你做整站归档,可以追加-e robots=off关闭 robots 解析;同时把层级限制放开,用--level=inf或直接依赖--mirror内置的无限层级;如果问题出在动态链接上,改用 sitemap.xml 做种子 URL,把有效链接一次性喂给 wget,绕过递归审理。sitemap 种子抓法在第 3 章已经给出过命令,这里不再重复。
4.2 图片全裂,样式全丢
现象:页面能打开,结构也在,但所有图片位置都是裂图,CSS 完全没有作用。打开本地目录却发现 CSS 文件存在,图片也存在,就是路径不对。
原因:源站把静态资源放在了独立域名下,且 HTML 里写的是带域名的绝对路径。wget 抓取时虽然把资源下载下来了,但--convert-links没有把这些跨域绝对路径改写成相对路径,或者改写规则不满足当前目录层级。另一种常见情况是防盗链,图片请求带了错误的 Referer 头,服务端返回 403,本地落地的图片文件全是 0 字节。
解决:先用第 3 章的 grep 统计域名命令,确认资源实际来源于哪些域名。如果资源已抓到,用 sed 把源站域名替换成根相对路径;如果资源没抓到,把对应域名追加到--domains白名单重新抓取。对于防盗链,wget 抓取时加 Referer 头伪装来源页码:
wget --mirror --page-requisites --convert-links \ --referer="https://docs.example.com/" \ --domains docs.example.com,static.example.com \ --directory-prefix=./site_backup \ https://docs.example.com/抓完检查 0 字节文件是最快的验证手段,find命令见第 5 章。
4.3 页面返回 403 或频繁断连
现象:抓取过程中大量请求返回 403,或者连接在抓到一半时突然中断,重跑还是同样位置失败。
原因:最常见的是两个——请求 UA 被服务端识别为非浏览器,以及请求频率太高触发了限流。wget 默认 UA 是Wget/x.x.x,几乎所有带基础防护的站点都会拦这串标识。另外并发参数太高时,短时间内的密集请求极易触发 IP 级别的临时封禁。
解决:给 wget 设置完整的浏览器 UA,同时加上请求间隔和重试限制。间隔参数前面已经讲过,重试方面追加--tries=3 --retry-connrefused让断连时自动重试。如果站点防护严格,把--wait从 2 秒提高到 5 秒,宁可抓得慢也不要触发封禁。还有一点容易被忽略:--tries设得太高配合--wait太短,反而会放大被限流的概率,因为重试本身也是高并发请求。
4.4 中文乱码与编码混乱
现象:抓下来的 HTML 在浏览器里显示乱码,或者页面文件名乱码,链接点进去 404。
原因:源站返回的 Content-Type 声明的字符集与实际内容编码不一致。比如内容实际是 GBK,服务器却声明了 UTF-8,wget 在抓取时按服务器声明解析,导致链接改写阶段解析出错,文件名和链接就全乱了。这种情况在国内老系统上格外常见,属于“技术债”重灾区。
解决:先确认文件真实编码,再批量转码。用file命令抽查一批 HTML 文件:
file -i $(find ./site_backup -name "*.html" | head -20)输出里会显示每个文件的charset=信息。如果确认是 GBK,手动转码:
for f in $(find ./site_backup -name "*.html"); do iconv -f GBK -t UTF-8 "$f" > "$f.tmp" && mv "$f.tmp" "$f" done这条命令把每个 GBK 编码的 HTML 转成 UTF-8 并原地覆盖。前提是你已经确认文件确实是 GBK,如果源文件本来就是 UTF-8,用-f GBK强制转码会产生二次乱码。所以先 file 抽查再动手,这个顺序不能乱。
4.5 抓回来一大片外部域名内容
现象:站点备份目录里除了目标站点,还出现了 cdn.example.org、fonts.example.net、img.example.co 等一堆目录,体积膨胀了好几倍,很多内容根本与目标站无关。
原因:--span-hosts把跨域资源也抓下来了,但--domains白名单没有同步配置,或者白名单写错域名导致部分第三方域不受控。--span-hosts的本意是允许抓取页面上引用的外部资源,但加了它却不加白名单,等于允许抓取所有域名。
解决:抓取命令里必须给--domains指定明确的白名单,只放行目标站和确实承载静态资源的已知域名。如果已经抓完且混入了外部域名,先识别再清理:
find ./site_backup -maxdepth 1 -mindepth 1 -type d \ ! -name "docs.example.com" ! -name "static.example.com" \ -exec rm -rf {} +这条命令删除站点根目录下不属于白名单的目录。执行前先确认目录名确实是对应外部域名,千万不要把主站目录误删了。
5. 把站点本地化跑通:静态服务器、路由策略与完整性验证
资源抓完、链接改好,只是静态文件的准备工作。真正能打开浏览,还要在本地起一个服务环境。这一章解决三个问题:本地静态服务怎么起、history 路由白屏怎么兜底、以及怎么验证抓取是否完整。
5.1 本地起静态服务:一个命令启动,注意 Base 路径
如果你的站点是纯静态页面,且--convert-links已经把链接改成相对路径,最简单的浏览方式是用协议头file://直接双击 HTML。但这里有一个明显问题:浏览器对file://协议下的 AJAX 请求有限制,而且如果页面里有fetch('data.json')这类相对请求,file://下大概率直接失败。所以靠谱的做法是起一个本地 HTTP 服务。
Python 自带的方式最简单:
cd /path/to/site_backup/docs.example.com python3 -m http.server 8080 --bind 127.0.0.1--bind 127.0.0.1表示只在本机访问,适合离线预览;如果想要局域网内其他设备也能访问,把 bind 地址改成0.0.0.0。这里有一个反复踩坑的地方:cd进的目录必须是站点根目录,也就是备份目录里以域名为名字的那层,比如/backup/docs.example.com而不是/backup,否则根相对路径/assets/style.css会找不到文件。如果页面里大量使用根相对路径,服务根目录就必须和路径根对齐。
如果用的是 Node 环境,npx serve也能达到同样效果,但它不是 Python 那种“当前目录就是根目录”的逻辑,默认根目录是执行命令的目录。两种方式选一个就行,不建议混用,否则容易搞混服务的实际根路径。
5.2 路由策略:hash 路由能打开,history 路由白屏的兜底方案
这一步是区分前端开发和纯运维经验的关键点。如果目标站点用的是 hash 路由,URL 长这样:/#/user/list,那么静态服务器几乎不用做任何处理,因为#后面的路径是浏览器端解析的,HTTP 服务器拿到的请求永远是首页路径,所有路由切换都在客户端 JS 里完成,本地浏览没有任何障碍。
如果是 history 路由,URL 长这样:/user/list,情况就变了。当你直接访问本地服务器的/user/list时,Python 的 http.server 会去找user/list对应的物理文件,但本地文件系统里根本没有这个路径,于是返回 404。这就是典型的“首页能打开,一刷新或手输地址就白屏”。
解决 history 路由白屏的兜底方案是把所有未命中的路径统一回退到index.html,让前端路由接管。用 nginx 做本地服务时配置如下:
server { listen 8080; server_name 127.0.0.1; root /path/to/site_backup/docs.example.com; location / { try_files $uri $uri/ /index.html; } }try_files的匹配顺序是:先找真实的$uri文件,找不到就找$uri目录,目录也不存在就统一返回/index.html,这样前端路由就能接管所有未命中路径。没有 nginx 时,用 Node 的serve带-s参数也能实现同样的 fallback:
npx serve -s ./site_backup/docs.example.com -l 8080-s是 single-page 模式,行为等价于上面那段 nginx 配置。需要注意的是,如果站点原本就有子路径部署,比如线上部署在/docs/下,本地 fallback 也要对应加上前缀,否则资源路径仍然对不上。
5.3 完整性自查:用脚本统计资源缺口
抓完以后不能直接归档,我一般会跑一轮自查脚本,核心是统计 HTML 数量、检查 0 字节文件、看文件类型分布是否合理。
echo "HTML: $(find ./site_backup -name '*.html' | wc -l)" echo "CSS: $(find ./site_backup -name '*.css' | wc -l)" echo "JS: $(find ./site_backup -name '*.js' | wc -l)" echo "Zero-byte files: $(find ./site_backup -type f -size 0 | wc -l)" echo "Top file types:" find ./site_backup -type f | sed 's/.*\.//' | sort | uniq -c | sort -rn | head -10前四行分别统计 HTML、CSS、JS 和 0 字节文件数量。0 字节文件数量不为 0 时,直接指向两种可能:请求被服务端拒绝,或者源站返回了空内容,这在防盗链和第 4.2 节的问题里最常见。Top file types 那一段输出的是文件类型分布,可以用来快速判断抓取是否有明显缺口——比如一个正常的文档站,图片数量和 HTML 数量至少是同一量级,如果 HTML 有几百个而图片只有个位数,说明图片资源大概率在抓取阶段被遗漏了。
数量统计之外,还要抽查页面是否能正常打开。启动本地服务后,从首页里提取几个真实链接,用 curl 验证本地响应状态:
for u in $(grep -oE 'href="[^"]*\.html"' ./site_backup/docs.example.com/index.html \ | sed 's/href="//;s/"//' | head -5); do code=$(curl -s -o /dev/null -w "%{http_code}" "http://127.0.0.1:8080$u") echo "$u -> $code" done这段脚本从首页的 HTML 里提取 .html 链接,拼上本地服务地址请求。如果输出里出现 404,说明链接改写或文件组织还有问题。注意 sed 提取出来的链接如果是相对路径,拼接时要以根路径为基准,确保 URL 路径与本地目录结构一致。抽查三个页面就够了,重点是确认“链接编写正确 + 资源文件存在”这两件事同时成立。
6. 带数据的整站抓取:登录态、接口归档与抓后自查习惯
前面的章节默认抓取的是公开可访问页面,但现实里经常遇到需要登录才能看的站点,以及纯前端渲染、必须抓接口才能拿到数据的场景。这一章是进阶操作,核心是把登录态和接口数据这两块补上,再沉淀一个抓后自查的固定习惯。
6.1 带 cookie 抓取登录后才能访问的页面
很多站点公开首页可以访问,但文档详情、后台页面需要登录。wget 支持通过--load-cookies加载浏览器导出的 cookie 文件,文件格式要求是 Netscape 格式。主流浏览器插件都能一键导出,导出后保存为 cookies.txt 再执行:
wget --mirror --page-requisites --convert-links \ --load-cookies=cookies.txt \ --keep-session-cookies \ --domains docs.example.com,static.example.com \ --directory-prefix=./site_backup \ https://docs.example.com/注意 cookie 文件一旦过期,抓取就会在登录墙处停止,不会报错,只是抓下来的页面数量明显变少。所以抓完以后必须回来看 HTML 文件数量是否合理,这是判断登录态是否失效最直接的方式。
6.2 接口数据直连归档:用 curl 按分页拉 JSON
对于纯前端渲染的站点,直接抓 HTML 得到的是空壳。更务实的做法是抓它背后的数据接口,把 JSON 按分页落盘,后续直接用 JSON 重建页面。常见接口是分页参数加页码,循环拉取即可:
for i in $(seq 1 20); do curl -s "https://api.example.com/v1/items?page=$i&page_size=50" \ -H "Cookie: SESSION=xxx" \ -H "Accept: application/json" \ -o "./data/page_$i.json" sleep 1 doneseq 1 20表示拉取前 20 页,每页 50 条,共 1000 条数据;-H传入认证头和 Cookie,-o指定输出文件。这里不建议直接改 wget 抓接口,因为 JSON 接口的请求头更复杂,curl 控制更细腻。拉完以后检查每个 JSON 文件大小,如果某页小于 1KB,大概率是接口返回了错误信息而不是数据。
6.3 抓后的安全与归档习惯:先验证再离线保存
归档前有一个容易被忽视的安全点:抓下来的 HTML 里可能包含用户个人信息,或者接口 JSON 里包含内网 IP、敏感 token,直接打包交给别人会有泄露风险。我现在的习惯是归档前先跑一次关键词扫描,把邮箱、手机号、token 类字段过滤掉再打包。
从那以后,我每次做整站下载都会强制走一遍同样的流程:先用 curl 判断目标站是否动态渲染,再按渲染类型选抓 HTML 还是抓接口,抓完后跑 0 字节检查和文件类型分布统计,最后启动本地服务抽查三个真实页面。这套流程看起来多花十分钟,但能挡掉大部分返工——有一回抓完整个站,发现字体子集化文件全是 0 字节,几百个页面的排版和字体全崩了,如果当时直接归档,交付出去就是一次事故。希望帮到你。
本文还有配套的精品资源,点击获取