我们的立场声明如下:我们是 Geonode,我们销售代理服务,但此类用途几乎不需要代理。镜像一个已获授权的网站是一项单一来源、流量适中的任务,通过您自己的网络连接即可顺利运行。 如果您正在考虑为此使用代理,这通常意味着您的镜像速度超出了该网站的容忍范围,正确的解决方法是降低速度,而不是分散流量。只有一种真正的例外情况——镜像特定地区的区域内容——下文将对此进行说明。本文中提到的其他所有方法,仅需一台笔记本电脑即可实现,完全不需要任何基础设施。
这些工具的实际功能
该类别中的每款工具都包含四个步骤。
抓取页面。 下载 HTML 文件。 查找资源。 解析图片、样式表、脚本和字体,并追踪这些资源。 追踪链接。 在您定义的范围内发现更多页面。 重写引用。 将绝对 URL 转换为相对路径,以便副本可在您的文件系统中正常运行。
正是第四步将“抓取工具”与“爬虫”区分开来。爬虫用于收集数据;抓取工具则生成可浏览的本地副本,而链接重写正是两者的关键区别。
其合法用途并不出人意料:在网站下线前进行归档;将文档下载到本地以便在旅途中或受限网络中使用;进行平台间迁移;保留合规记录;以及在主机关闭时保存自己的作品。
wget:首选方案
大多数 Unix 系统中已预装,且足以胜任大部分任务。
wget --mirror --convert-links --adjust-extension --page-requisites \
--no-parent --wait=1 --random-wait \
https://example.com/docs/
每个选项都有其存在的理由,wget 手册 对这些选项有详细说明。
**--mirror
** “启用适合镜像下载的选项。此选项会启用递归下载和时间戳功能,将递归深度设为无限,并保留 FTP 目录列表。目前它等同于 -r -N -l inf --no-remove-listing
。”
**--page-requisites
** “使 Wget 下载所有必要文件,以便正确显示给定的 HTML 页面。这包括内联图片、声音以及引用的样式表等内容。”如果不使用该选项,生成的 HTML 页面将没有样式且没有图片。
**--convert-links
** 会在“下载完成后……重写引用,使其适合本地查看”,这不仅影响“可见的超链接,还包括文档中任何链接到外部内容的部分”。
**--adjust-extension
** 会为那些以 HTML 格式提供但未带 HTML 扩展名的页面追加 .html
—— 手册中举例说明:“镜像一个使用 .asp 页面的远程站点,但你希望镜像后的页面能在你的标准 Apache 服务器上查看”。
**--no-parent
** 确保“仅下载特定层级下的文件”,这正是将任务范围限定在 /docs/
而非整个网站的原因。
**--wait=1
** 是一个礼貌标志,手册明确推荐使用它:“建议使用此选项,因为它能减少请求频率,从而减轻服务器负载。”将其与 --random-wait
配合使用,手册中指出该选项是“受这一不恰当建议的启发——即因某人的行为而将许多无关用户拒之门外”。
还有两个值得了解的选项。-Q
可设置下载配额,以防止无限制的镜像下载占满你的磁盘空间。而 -l
可设置递归深度,如果将递归深度设为 infinite 过于宽松的话。
wget 确实存在一些局限性:它无法运行 JavaScript,其链接重写功能虽然不错,但在复杂网站上并非完美,而且它没有图形界面。对于文档网站或静态博客而言,这些都不成问题。
HTTrack:经典的图形化工具
HTTrack 是该领域最知名的专用工具,属于开源、跨平台软件,同时支持图形界面和命令行操作。该项目至今仍在持续维护中。
其优于 wget 的地方在于:为不习惯使用终端的用户提供了真正的图形界面,能更好地处理复杂的链接结构,支持项目断点续传,以及仅对已更改内容进行镜像的更新模式。
其不足之处:同样存在根本性限制——无法执行 JavaScript——此外,其过滤语法需要一定学习成本,且因在网站运营者中声名不佳,部分网站会根据用户代理将其屏蔽。
对于需要静态网站可浏览副本的非技术用户,这是首选方案。对于熟悉 shell 的用户,wget 也能完成同样的工作,且更少意外。
单页工具
这是一种不同类型的问题,但往往正是解决问题的正确方法。
如果你想要的只是一页完整的页面,而不是整个网站,那么将所有内容内联到一个独立的HTML文件中的工具,比镜像网站更有用。 它们将图片作为数据 URI 嵌入,内联 CSS,并生成一个无需任何依赖的文件,你可以通过电子邮件发送、归档或在任何地方打开。
这一类别的浏览器扩展对大多数人来说是更实用的选择,而且它们比这里提到的所有命令行工具都具有一个决定性的优势:它们捕获的是 JavaScript 运行后渲染出的页面。 对于现代应用程序而言,这正是可运行副本与空壳之间的区别。
其取舍在于操作需要手动完成——每次仅限一页,且需人工点击。对于寥寥数页尚可接受;但若涉及上千页,则难以承受。
ArchiveBox 与保存工具
当目标是数据保存而非离线浏览时,ArchiveBox 是一个值得关注的选择。它接受 URL 作为输入,并能一次性生成多种存档格式——HTML、屏幕截图、PDF、提取的文本以及 WARC 文件。
WARC 是一种值得了解的格式,因为它是网络归档机构所采用的标准。它存储的是 HTTP 交易本身,而非文件系统的近似副本,这意味着请求头、状态码和精确的字节数据均被完整保留。对于任何注重数据准确性的场景——例如法律、合规性或研究——这种格式相比重新编写的 HTML 目录,能提供实质上更优质的记录。
ArchiveBox 支持自主托管,维护索引,并通过驱动无头浏览器来处理 JavaScript。它比 wget 更复杂,但生成的存档更持久。
为什么它们都难以应对现代网站
这一类别中大多数令人失望现象背后的唯一原因。
JavaScript 渲染。 wget 和 HTTrack 会抓取 HTML 并对其进行解析。单页应用程序返回的是一份几乎为空的文档以及一个脚本包,内容是在浏览器中组装而成的。你所镜像的只是外壳。
API驱动的内容。 即使初始HTML包含内容,后续导航也可能从API获取JSON数据。这些请求是由代码发起的,而非标记中的链接,因此基于链接遍历的镜像工具永远无法发现它们。
无限滚动和懒加载。 通过交互显示的内容根本不存在于标记中。
客户端路由。 这些 URL 永远不会触及服务器。镜像无法获取从未被请求过的内容。
身份验证和个性化。 任何需要登录才能访问的内容,以及因用户而异的内容。
解决方法,按工作量由低到高排序:
检查是否有静态导出。 文档网站通常提供 PDF 或可下载的资源包。在构建之前先询问。
**检查是否提供 API。**如果内容来自 API,直接获取比镜像前端更简单且更完整。
对于确实需要渲染的页面,使用基于浏览器的工具。 Playwright 可以进行页面导航、等待内容加载并保存渲染后的 HTML,这相当于一个支持 JavaScript 的镜像,但需要编写脚本且会消耗更多带宽。
接受部分镜像。 对于许多用途而言,网站的静态部分本来就是你所需要的。
使用 Playwright 镜像 JavaScript 网站
当传统工具返回空壳时,这是一个实用的备选方案。它并非通用的网页抓取工具,但足以捕获一组已定义页面的渲染结果。
import { chromium } from 'playwright';
import { writeFile, mkdir } from 'fs/promises';
import { dirname } from 'path';
const urls = [/* the pages you want */];
const browser = await chromium.launch();
const ctx = await browser.newContext();
const page = await ctx.newPage();
for (const url of urls) {
await page.goto(url, { waitUntil: 'domcontentloaded' });
await page.waitForSelector('main', { timeout: 15000 }).catch(() => {});
const html = await page.content(); // rendered DOM, not source
const path = 'mirror' + new URL(url).pathname.replace(/\/$/, '/index') + '.html';
await mkdir(dirname(path), { recursive: true });
await writeFile(path, html);
await page.waitForTimeout(1000 + Math.random() * 1000);
}
await browser.close();
其中有四点值得注意。
**page.content()
返回的是渲染后的 DOM**,而非源 HTML。这正是该方法能在 wget 失效时依然奏效的根本原因——你获取的是 JavaScript 构建完成后实际存在的标记结构。
等待特定选择器,而非等待网络空闲。 包含分析信标或 WebSocket 的页面永远不会处于空闲状态,因此在许多现代网站上,waitUntil: 'networkidle'
会直接超时。等待一个已知必定存在的元素,既更快又更可靠。
页面之间的刻意暂停。 这与 wget 中的 --wait
选项同理,且同样必要。
不进行链接重写。 这是客观的局限:你获取的是包含绝对路径的渲染后 HTML,因此要正确显示内容,副本需要联网。 添加重写功能意味着需要解析每个文档、下载所有资源并重写引用——这相当于重新实现 wget,而到了这一步,将两者结合反而更简单:使用 Playwright 进行渲染并保存,然后对保存的文件运行 wget 以收集资源。
此外还要考虑带宽成本。 浏览器会预加载每张图片、字体、脚本和视频,因此与使用 wget 镜像相同页面相比,这会消耗大约多出一个数量级的流量。如果要保留的内容中不包含这些元素,可以通过 page.route()
阻止字体和媒体请求,从而大幅减少流量消耗。
选择工具
| 需求 | 工具 |
|---|---|
| 静态网站,习惯使用终端 | wget |
| 静态网站,偏好图形界面 | HTTrack |
| 单页网站,内容完整且自成体系 | 单文件浏览器扩展程序 |
| 高保真度存档 | ArchiveBox / WARC |
| JavaScript 内容繁多的网站 | Playwright 脚本 |
| 迁移前的自有网站 | 所在平台的导出功能 |
最后这一行值得单独说明,因为人们往往会用最费力的方式来解决这个问题。 如果你是网站所有者,请使用平台提供的导出功能。 无论是数据库导出、静态网站构建还是主机服务商的备份,这些方法都完整无缺,包含镜像无法捕获的内容,且只需几分钟即可完成。对自己的网站进行镜像,无异于将一件简单的事情搞得复杂化。
无论如何都适用的规则
与工具无关。
robots.txt 适用于您。 wget 默认会遵守该规则。HTTrack 默认也会遵守该规则。虽然可以设置这两款工具不遵守该规则,但这样做是一种有后果的刻意选择。 这现已成为一项标准——RFC 9309——我们在如何阅读 robots.txt 文件一文中已介绍过如何解读该文件。
速率限制并非可选项。 未设置 --wait 的镜像站点会以连接允许的最快速度发送请求,这在服务器端看来与攻击无异。每秒一个请求是一个合理的下限。
版权不会消失。 下载一份副本供个人离线阅读是一回事;重新发布则是另一回事。内容仍归所有者所有。
服务条款可能会直接禁止此行为,无论技术上是否可行。
**带宽会给网站带来成本。**一个大型网站的镜像可能需要传输数吉字节的数据,而这些成本最终需要有人承担。
**请先询问。**对于任何重要请求,发送一封电子邮件比寻找变通方法更快。网站所有者通常会同意,有时甚至会提供打包资源,让你完全省去这些麻烦。
代理的适用场景简述
既然这是我们的产品,坦率地说,答案很简单。
您不需要代理来镜像一个您已获授权、且能以合理速率从单一位置进行镜像的网站。这占了绝大多数的合法使用场景,仅需单个连接即可处理。
你可能需要使用代理,如果该网站根据地区提供不同的内容,而你想要获取区域版本——例如包含本地化页面的文档网站,或提供特定国家库存的商品目录。这种情况下,地理位置是关键,这属于真正的使用场景。
您无需使用它们来提高速度,若出于此目的而使用它们,则意味着您的镜像速度已超出该网站可接受的范围。对此的正确应对方式是 --wait,而非使用分发服务。
如果属于区域性场景,数据中心带宽是明智的选择——我们的起价为 0.14 美元/GB(2026 年 9 月根据我们的 定价页面 核查)——请注意,完整镜像的流量以千兆字节为单位计算,因此计算结果至关重要。
大家还问
什么是网站抓取工具?
这是一种将网站页面和资源下载到本地存储,并重写链接以便离线访问的工具。这种链接重写功能正是它与爬虫的区别所在——爬虫仅收集数据,而非生成可浏览的镜像网站。
如何下载整个网站?
wget --mirror --convert-links --adjust-extension --page-requisites --no-parent --wait=1 URL 适用于大多数静态网站。若需要图形化操作,HTTrack 也能完成相同任务。对于 JavaScript 内容较多的网站,上述两种工具均难以胜任,此时需要采用基于浏览器的解决方案。
为什么我下载的网站看起来有问题?
通常是因为缺少 --page-requisites,导致样式表和图片未被抓取;或者缺少 --convert-links,导致引用仍指向在线网站。如果页面是空的而非未应用样式,则说明该网站通过 JavaScript 渲染内容,而非渲染类工具无法捕获这些内容。
下载网站是否合法?
出于个人离线使用目的进行下载通常无伤大雅;但重新发布则是另一回事,因为版权依然适用。服务条款可能会明确禁止自动化下载,无论采用何种技术手段。具体情况因司法管辖区而异,本文不构成法律建议。
我可以下载使用 JavaScript 的网站吗?
使用 wget 或 HTTrack 无法实现,因为它们在抓取和解析 HTML 时不会执行脚本。你需要采用基于浏览器的方法——针对单个页面使用单文件扩展程序,或者使用 Playwright 脚本进行导航、等待内容加载并保存渲染结果。
最好的免费网站下载工具是什么?
如果你熟悉命令行,建议使用 wget,因为它通常已预装,且完全能够处理静态网站。如果你需要图形界面,建议使用 HTTrack。如果你的目的是保存而非浏览,建议使用 ArchiveBox,因为它除了生成 HTML 文件外,还会生成 WARC 文件。
如何下载网站而不被封锁?
在每次请求之间设置至少一秒的延迟,遵守 robots.txt 规范,如实标识自身身份,并通过 --no-parent 及深度限制来控制范围。此类封锁大多源于全速镜像下载,从服务器角度看,这与攻击行为毫无二致。
下载网站时是否应该使用代理?
仅当您需要特定地区版本的内容时才需使用。对于以合理速率进行的普通镜像下载,一条连接就足够了。若为了提速而使用代理,则意味着您的传输速率超出了网站允许的范围,此时只需设置延迟标志即可解决。
总结
对于静态网站而言,这个问题早已迎刃而解,而且所需工具已经安装在你的机器上了。只需一条带有五个参数的 wget 命令,就能生成一个可浏览的本地副本,而人们最容易忘记的那个参数,正是让它“彬彬有礼”的那个。
对于现代应用程序,经典工具均无法奏效,而原因并非可以通过配置来弥补的缺陷。这些工具仅能获取并解析 HTML;内容是在获取之后由 JavaScript 组装而成的。 现实可行的方案包括:针对关键页面使用基于浏览器的抓取、若存在 API 则调用 API,或者如果你拥有该网站则使用导出功能——而最后一种情况往往需要通过艰难的方式才能解决。
无论你使用什么工具,有三点是通用的:实施速率限制,因为全速镜像与攻击难以区分;遵守 robots.txt 规范,因为这是标准,而忽略它是一种选择;对于任何重要内容,请先询问——发一封邮件只需一分钟,而且往往能获得一揽子资料,从而使整个操作变得多余。
