最简单、最推荐的方法 - 使用浏览器开发者工具

对于绝大多数用户和开发者来说,这是最快、最可靠的方法,因为它利用了浏览器内置的强大功能。

javascript 下载网页中所有资源
(图片来源网络,侵删)

步骤:

  1. 打开开发者工具:在目标网页上,按 F12Ctrl+Shift+I (Windows/Linux) / Cmd+Opt+I (Mac) 打开开发者工具。
  2. 切换到 "Network" (网络) 面板:点击顶部的 "Network" 标签页。
  3. 刷新页面:按 F5 刷新页面,这会记录下页面加载时发起的所有网络请求。
  4. 保存所有文件
    • 在 "Network" 面板中,按 Ctrl+A (Windows/Linux) / Cmd+A (Mac) 全选所有请求。
    • 右键点击任意一个请求,选择 "Save as HAR with content..." (或类似名称,中文版可能是“另存为包含内容的 HAR...”)。
    • 选择一个保存位置,文件会以 .har 的格式保存下来。

什么是 HAR 文件? HAR (HTTP Archive) 是一个 JSON 格式的文件,它包含了所有网络请求的元数据(URL、请求头、响应头等)以及完整的响应内容(图片、CSS、JS 文件的二进制数据)。

如何从 HAR 文件中提取资源? 你需要写一个简单的脚本来解析这个 HAR 文件,下面是一个 Node.js 示例:

// 你需要先安装 har-parser: npm install har-parser
const harParser = require('har-parser');
const fs = require('fs');
const path = require('path');
// 1. 读取 HAR 文件
const harContent = JSON.parse(fs.readFileSync('your-file-name.har', 'utf8'));
// 2. 创建一个输出目录
const outputDir = 'downloaded-resources';
if (!fs.existsSync(outputDir)) {
    fs.mkdirSync(outputDir);
}
// 3. 遍历 HAR 中的每个条目(每个网络请求)
harParser.entries(harContent).forEach(entry => {
    // 忽略一些不需要的条目,如文档本身、字体等(可选)
    // if (entry.request.url.endsWith('.html') || entry.request.url.endsWith('.woff')) {
    //     return;
    // }
    const url = entry.request.url;
    const content = entry.response.content;
    const mimeType = content.mimeType;
    // 根据内容类型决定文件扩展名
    let extension = '.bin'; // 默认扩展名
    if (mimeType.includes('javascript')) extension = '.js';
    else if (mimeType.includes('css')) extension = '.css';
    else if (mimeType.includes('html')) extension = '.html';
    else if (mimeType.includes('image/')) {
        extension = '.' + mimeType.split('/')[1]; // e.g., .png, .jpg
    }
    // ... 可以添加更多类型判断
    // 从 URL 中提取文件名,或使用一个生成的 ID
    const fileName = path.basename(url.split('?')[0]) || `file_${entry.id}${extension}`;
    // 将 base64 编码的内容解码为 Buffer
    const buffer = Buffer.from(content.text, 'base64');
    // 写入文件
    const filePath = path.join(outputDir, fileName);
    fs.writeFileSync(filePath, buffer);
    console.log(`Downloaded: ${url} -> ${filePath}`);
});
console.log('All resources downloaded successfully!');

优点:

javascript 下载网页中所有资源
(图片来源网络,侵删)
  • 极其简单:无需编写复杂的下载逻辑。
  • 功能强大:能捕获到通过 JavaScript 动态加载的资源(如 AJAX 请求)。
  • 准确无误:包含了资源的原始内容和所有请求信息。

缺点:

  • 需要手动操作。
  • 需要一个额外的解析脚本来提取文件。

使用浏览器扩展程序

如果你需要频繁执行此操作,编写一个浏览器扩展是最佳选择,扩展可以完全控制网页,并拥有下载文件的权限。

核心思路:

  1. manifest.json: 声明扩展的权限,特别是 activeTabdownloads API。
  2. background.jspopup.js: 用户点击扩展图标时触发下载逻辑。
  3. 内容脚本 (content_script.js): 注入到目标网页中,用于收集所有资源的 URL。

示例 content_script.js 逻辑:

javascript 下载网页中所有资源
(图片来源网络,侵删)
// 收集页面中所有链接的资源
function collectResourceUrls() {
    const resources = new Set();
    // 1. 获取所有 <img>, <script>, <link>, <source>, <track> 等标签的 src 或 href
    document.querySelectorAll('img, script, link, source, track, embed, object, iframe').forEach(el => {
        const src = el.src || el.href;
        if (src && !src.startsWith('data:')) { // 忽略 data URL
            resources.add(src);
        }
    });
    // 2. 获取所有内联样式中的图片 (background-image)
    document.querySelectorAll('style, [style]').forEach(el => {
        const style = el.getAttribute('style') || el.textContent;
        const urlRegex = /url\(["']?(.*?)["']?\)/g;
        let match;
        while ((match = urlRegex.exec(style)) !== null) {
            const url = match[1];
            if (url && !url.startsWith('data:')) {
                resources.add(url);
            }
        }
    });
    // 3. 获取所有内联脚本中的 fetch/ajax 请求 (这个比较复杂,通常需要更复杂的拦截逻辑)
    // ... 这里省略了复杂的网络请求拦截代码 ...
    return Array.from(resources);
}
// 将收集到的 URL 发送给 background script
const urls = collectResourceUrls();
chrome.runtime.sendMessage({ action: 'downloadResources', urls: urls });

示例 background.js 逻辑:

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
    if (request.action === 'downloadResources') {
        const urls = request.urls;
        console.log(`Received ${urls.length} URLs to download.`);
        urls.forEach(url => {
            // 使用 chrome.downloads API 下载文件
            chrome.downloads.download({
                url: url,
                saveAs: false // 自动下载,不弹出保存对话框
            }, (downloadId) => {
                console.log(`Downloading ${url} with ID: ${downloadId}`);
            });
        });
    }
});

优点:

  • 自动化:一键操作,非常方便。
  • 功能强大:可以精确控制下载行为(如文件名、保存路径)。
  • 用户体验好:集成在浏览器中。

缺点:

  • 需要学习浏览器扩展开发。
  • 需要用户安装扩展。

纯前端 JavaScript (不推荐,但有教育意义)

重要提示: 出于安全和隐私原因,现代浏览器(尤其是 Chrome)对网页的下载行为有严格限制。一个网页上的 JavaScript 无法直接触发下载另一个域名的文件,因为这会带来巨大的安全风险(CSRF 攻击等),这个方案有严重的局限性

局限性:

  1. 跨域限制:如果资源文件(如图片、CSS)与当前网页的域名不同,fetch 请求会因为 CORS 策略而失败,你无法获取其内容。
  2. 同源策略:即使资源是同源的,你也需要服务器配置正确的 Content-Disposition 响应头,否则浏览器会直接在标签页中显示内容(如图片、PDF),而不是触发下载。
  3. 无法下载字体和视频:这些资源通常有更严格的 CORS 策略。

代码示例 (仅适用于同源资源且浏览器支持下载的场景):

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">Resource Downloader (Limited)</title>
    <style>
        #downloadBtn { padding: 10px 20px; font-size: 16px; cursor: pointer; }
    </style>
</head>
<body>
    <h1>Simple Resource Downloader</h1>
    <button id="downloadBtn">Download All Resources</button>
    <script>
        document.getElementById('downloadBtn').addEventListener('click', async () => {
            const resources = [];
            // 收集同源资源
            document.querySelectorAll('img, script, link').forEach(el => {
                const src = el.src || el.href;
                if (src && new URL(src).origin === window.location.origin) {
                    resources.push(src);
                }
            });
            console.log('Found resources:', resources);
            for (const url of resources) {
                try {
                    // 1. 获取资源内容
                    const response = await fetch(url);