You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:修改Chrome扩展实现多序列全页面截图功能

解决方案:实现Chrome扩展全页多序列截图并合成PDF

当前你的扩展使用chrome.tabs.captureVisibleTab仅能捕获可视区域,要实现全页截图+多序列合成PDF,我们可以通过**Chrome DevTools Protocol(CDP)**实现原生全页截图,再用jsPDF将多图合并为PDF。以下是具体修改方案:


一、权限配置(manifest.json)

首先需要添加debugger权限以调用CDP命令,更新后的manifest.json如下:

{
  "manifest_version": 3,
  "name": "全页多序列截图转PDF",
  "version": "1.0",
  "permissions": ["tabs", "downloads", "scripting", "storage", "debugger"],
  "background": {
    "service_worker": "background.js"
  },
  "action": {
    "default_popup": "popup.html"
  },
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["content.js"]
    }
  ]
}

二、核心代码修改(background.js)

1. 引入jsPDF库

从jsPDF官网下载minified版本,保存为jspdf.min.js放入扩展目录,在background.js开头引入:

importScripts('jspdf.min.js');

2. 替换可视区域截图为全页截图

新增CDP全页截图函数,并替换原有的capture逻辑:

// 用CDP捕获全页截图
async function captureFullPage(tabId) {
  return new Promise((resolve, reject) => {
    chrome.debugger.attach({ tabId }, "1.3", (attachErr) => {
      if (attachErr) {
        reject(attachErr);
        return;
      }

      chrome.debugger.sendCommand({ tabId }, "Page.enable", {}, (enableErr) => {
        if (enableErr) {
          chrome.debugger.detach({ tabId });
          reject(enableErr);
          return;
        }

        // 开启captureBeyondViewport实现全页捕获
        chrome.debugger.sendCommand(
          { tabId },
          "Page.captureScreenshot",
          { captureBeyondViewport: true, format: "png" },
          (screenshotResult) => {
            chrome.debugger.detach({ tabId });
            if (chrome.runtime.lastError) {
              reject(chrome.runtime.lastError);
            } else {
              resolve(`data:image/png;base64,${screenshotResult.data}`);
            }
          }
        );
      });
    });
  });
}

// 修改消息监听中的capture逻辑
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.action === 'startCapture') {
    console.log('Received startCapture message:', message.settings);
    startCapture(message.settings);
  } else if (message.action === 'stopCapture') {
    stopCapture();
  } else if (message.action === 'capture') {
    // 替换为全页截图
    captureFullPage(sender.tab.id)
      .then(screenshotUrl => sendResponse(screenshotUrl))
      .catch(err => {
        console.error('Full page capture failed:', err);
        sendResponse(null);
      });
    return true;
  } else if (message.action === 'download') {
    // 保留原有下载逻辑,但后续我们会用合成PDF替代单图下载
    const { screenshotUrl, folder } = message;
    const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
    const filename = `${folder}/screenshot-${timestamp}.png`;
    console.log('Downloading screenshot to filename:', filename);
    chrome.downloads.download({
      url: screenshotUrl,
      filename: filename
    });
  }
});

3. 新增多截图合成PDF功能

添加全局变量存储截图列表,以及合成PDF的函数:

let capturing = false;
let settings = {};
let capturedScreenshots = []; // 存储所有捕获的截图URL

// 合成截图为PDF
async function mergeScreenshotsToPdf(screenshotUrls, folder) {
  const doc = new jsPDF();
  const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
  const filename = `${folder}/screenshot-collection-${timestamp}.pdf`;

  for (let i = 0; i < screenshotUrls.length; i++) {
    const imgData = screenshotUrls[i].split(',')[1];
    const img = new Image();
    await new Promise(resolve => {
      img.onload = resolve;
      img.src = screenshotUrls[i];
    });

    // 适配PDF页面尺寸
    const pageWidth = doc.internal.pageSize.getWidth();
    const pageHeight = doc.internal.pageSize.getHeight();
    const scale = Math.min(pageWidth / img.width, pageHeight / img.height);
    const scaledWidth = img.width * scale;
    const scaledHeight = img.height * scale;

    if (i > 0) doc.addPage();
    doc.addImage(imgData, 'PNG', (pageWidth - scaledWidth)/2, (pageHeight - scaledHeight)/2, scaledWidth, scaledHeight);
  }

  // 生成并下载PDF
  const pdfBlob = doc.output('blob');
  const pdfUrl = URL.createObjectURL(pdfBlob);
  chrome.downloads.download({
    url: pdfUrl,
    filename: filename
  }, () => URL.revokeObjectURL(pdfUrl));
}

4. 修改捕获流程,收集截图后合成PDF

更新startCapture、takeScreenshot以及导航逻辑,改为收集截图后统一合成:

async function startCapture(newSettings) {
  capturing = true;
  settings = newSettings;
  capturedScreenshots = []; // 初始化截图列表

  console.log('Starting capture process with settings:', settings);

  chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
    if (tabs.length === 0) {
      console.error('No active tab found');
      return;
    }
    const activeTabId = tabs[0].id;

    if (settings.mode === 'automatic') {
      if (settings.navigationMode === 'htmlSelector' && settings.selector) {
        navigateAndCaptureBySelector(activeTabId, settings.selector);
      } else if (settings.navigationMode === 'extractedUrls') {
        chrome.storage.local.get('extractedLinks', (result) => {
          const links = result.extractedLinks || [];
          if (links.length > 0) {
            navigateAndCaptureByLinks(activeTabId, links);
          }
        });
      }
    } else {
      // 手动模式:捕获当前页后合成PDF
      chrome.scripting.executeScript({
        target: { tabId: activeTabId },
        func: takeScreenshot,
        args: [settings.folder]
      }, () => {
        setTimeout(() => {
          mergeScreenshotsToPdf(capturedScreenshots, settings.folder);
          capturing = false;
        }, 1000);
      });
    }
  });
}

// 修改takeScreenshot为收集截图,而非立即下载
function takeScreenshot(folder) {
  console.log('Taking screenshot, folder:', folder);
  chrome.runtime.sendMessage({ action: 'capture' }, (screenshotUrl) => {
    if (screenshotUrl) {
      console.log('Screenshot URL:', screenshotUrl);
      capturedScreenshots.push(screenshotUrl);
    }
  });
}

// 更新导航捕获逻辑,完成后合成PDF
function navigateAndCaptureBySelector(tabId, selector) {
  if (!capturing) return;

  chrome.scripting.executeScript({
    target: { tabId: tabId },
    func: (selector) => !!document.querySelector(selector),
    args: [selector]
  }, (results) => {
    const hasNextButton = results[0].result;
    if (hasNextButton) {
      chrome.scripting.executeScript({
        target: { tabId: tabId },
        func: (selector) => document.querySelector(selector).click(),
        args: [selector]
      }, () => {
        setTimeout(() => {
          chrome.scripting.executeScript({
            target: { tabId: tabId },
            func: takeScreenshot,
            args: [settings.folder]
          }, () => {
            navigateAndCaptureBySelector(tabId, selector);
          });
        }, 3000);
      });
    } else {
      // 无下一页,合成PDF
      mergeScreenshotsToPdf(capturedScreenshots, settings.folder);
      capturing = false;
      console.log('Capture completed, merged to PDF');
    }
  });
}

function navigateAndCaptureByLinks(tabId, links, index = 0) {
  if (!capturing || index >= links.length) {
    // 所有链接处理完毕,合成PDF
    mergeScreenshotsToPdf(capturedScreenshots, settings.folder);
    capturing = false;
    console.log('Capture completed, merged to PDF');
    return;
  }

  chrome.tabs.update(tabId, { url: links[index] }, () => {
    setTimeout(() => {
      chrome.scripting.executeScript({
        target: { tabId: tabId },
        func: takeScreenshot,
        args: [settings.folder]
      }, () => {
        navigateAndCaptureByLinks(tabId, links, index + 1);
      });
    }, 3000);
  });
}

// 更新停止捕获逻辑,合成已捕获的截图
function stopCapture() {
  capturing = false;
  if (capturedScreenshots.length > 0) {
    mergeScreenshotsToPdf(capturedScreenshots, settings.folder);
    console.log('Capture stopped, merged existing screenshots to PDF');
  } else {
    console.log('Capture process stopped, no screenshots captured');
  }
}

三、注意事项

  1. 调试器授权:首次使用扩展时,Chrome会提示授权调试器访问,需用户同意才能正常工作。
  2. 页面等待优化:当前固定3秒等待页面加载,可替换为监听chrome.tabs.onUpdated事件,直到标签状态变为complete再捕获,提升可靠性。
  3. 内存占用:若捕获大量页面,base64截图会占用较多内存,可考虑分批次合成或临时存储到本地。
  4. 跨域兼容:Chrome扩展的debugger权限允许跨域调试不同网站页面,但部分网站可能有反调试机制,需测试验证。

内容的提问来源于stack exchange,提问作者AtFirstYouTry

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 08:37:06