### [保存动态渲染后的 HTML:四种方案取舍](https://www.huociguo.com/article/1522) **Published:** 2026-09-30T05:14:40 **Author:** 米了 **Excerpt:** 右键另存为拿到的是原始源码,不是渲染后的 DOM。四种方案按可靠度分层,含 DevTools 复制、无头浏览器… `view-source` 与右键另存为拿到的都是服务端返回的原始 HTML,JavaScript 生成的节点不在其中。要保留渲染后的结果,得从 DOM 层取快照,按需求强度选方案。 ![电脑显示器上显示代码,用于说明渲染后 DOM 与原始源码的区别](https://api.huociguo.com/wp-content/uploads/2026/09/b5.jpg) 渲染后的 DOM 与服务端返回的源码不是同一份内容 ## 四种方案的差别 | 方案 | 拿到什么 | 适用场合 | 成本 | | --- | --- | --- | --- | | 浏览器另存为 | 原始 HTML 加资源 | 静态页、少量页面 | 低 | | 开发者工具复制 outerHTML | 当前 DOM 快照 | 单次取证、调试 | 低 | | curl 或 wget | 服务端响应原文 | 接口与静态页抓取 | 中 | | 无头浏览器 | 渲染后 DOM 加可选资源 | 批量、离线保存 | 高 | ## 单次取样:开发者工具 Elements 面板选中 `html` 节点,右键 Copy → Copy outerHTML,得到的是此刻完整的 DOM 字符串。SPA 页面要先操作到目标状态(展开、滚动加载完成)再复制,否则拿到的是半成品。 ## 批量保存:无头浏览器 ```js const html = await page.goto(url, { waitUntil: 'networkidle0' }); await page.evaluate(() => window.scrollTo(0, document.body.scrollHeight)); await page.waitForTimeout(1000); const dom = await page.content(); ``` - `waitUntil: 'networkidle0'` 等网络空闲,避免拿到未完成的渲染结果; - 先滚动到底再等待,覆盖懒加载内容; - `page.content()` 返回序列化后的 DOM,写文件即可得到快照。 ## 需要完整离线时 只保存 DOM 字符串并不能离线打开,图片、样式、字体仍指向远端。要可离线浏览,需要同时抓取资源并改写引用路径: ```js await page.setRequestInterception(true); // 拦截请求 → 落盘本地 → 改写 HTML 中的引用地址 ``` 资源抓取要注意跨域名限制、query 参数去重与文件名冲突,这三项是离线包最常见的失败点。 ## 取舍顺序 1. 只要一份渲染后的结构 → 开发者工具复制; 2. 要批量重复执行 → 无头浏览器取 page.content(); 3. 要可离线打开 → 在上一步基础上补资源抓取与路径改写; 4. 页面本身由服务端渲染 → curl 或 wget 已足够,无需引入浏览器。 **Tags:** DOM快照, DOM操作, 开发者工具, 无头浏览器, 源码保存 **Categories:** HTML5 ---