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

如何在严格CSP的网站上为Chrome扩展内容脚本运行WebWorker?

可行解决方案

针对Chrome扩展在CSP严格站点无法运行Tesseract.js Worker的问题,以下是几种无需每次新开标签的方案:

1. 使用扩展沙箱页面(Sandboxed Page)

沙箱页面是Chrome扩展提供的独立执行环境,不受宿主页面CSP限制,适合处理需要绕过CSP的脚本任务。

配置步骤

  • 在manifest.json中添加沙箱配置,指定允许脚本执行和本地资源访问:
{
  "manifest_version": 3,
  // 其他扩展配置...
  "sandbox": {
    "pages": ["sandbox.html"],
    "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"
  }
}
  • 将tesseract.min.js、worker.min.js及Tesseract语言包(如eng.traineddata)放在扩展目录下。

沙箱页面逻辑(sandbox.html)

创建专门处理OCR的沙箱页面,通过扩展消息系统接收截图数据并返回识别结果:

<!DOCTYPE html>
<html>
<body>
  <script src="tesseract.min.js"></script>
  <script>
    chrome.runtime.onMessage.addListener(async (msg, sender, sendResponse) => {
      if (msg.action === 'ocr') {
        // 初始化Worker,指定扩展内的资源路径
        const worker = await Tesseract.createWorker({
          workerPath: chrome.runtime.getURL('worker.min.js'),
          langPath: chrome.runtime.getURL('langs/'),
          lang: 'eng'
        });
        // 执行OCR识别
        const result = await worker.recognize(msg.imageData);
        await worker.terminate();
        // 返回识别文本
        sendResponse({ text: result.data.text });
      }
      return true; // 标记异步响应
    });
  </script>
</body>
</html>

内容脚本调用

内容脚本只需将截图数据(如base64格式的图片)发送给沙箱页面,等待结果返回:

// 假设已获取网页截图的base64数据
const screenshotBase64 = 'data:image/png;base64,...';

chrome.runtime.sendMessage({
  action: 'ocr',
  imageData: screenshotBase64
}, (response) => {
  console.log('OCR识别结果:', response.text);
});

2. 使用Offscreen Document(Chrome 109+)

Offscreen Document是Chrome 109版本引入的轻量级后台文档,专为扩展处理后台任务设计,无需显示UI,且完全隔离于宿主页面CSP。

配置步骤

  • 在manifest.json中注册Offscreen文档:
{
  "manifest_version": 3,
  // 其他扩展配置...
  "offscreen": {
    "matches": ["<all_urls>"],
    "documents": ["offscreen.html"]
  }
}

Offscreen页面逻辑(offscreen.html)

逻辑与沙箱页面类似,通过消息系统处理OCR任务:

<!DOCTYPE html>
<html>
<body>
  <script src="tesseract.min.js"></script>
  <script>
    chrome.runtime.onMessage.addListener(async (msg, sender, sendResponse) => {
      if (msg.action === 'runOcr') {
        const worker = await Tesseract.createWorker({
          workerPath: chrome.runtime.getURL('worker.min.js'),
          langPath: chrome.runtime.getURL('langs/'),
          lang: 'eng'
        });
        const result = await worker.recognize(msg.image);
        await worker.terminate();
        sendResponse({ text: result.data.text });
      }
      return true;
    });
  </script>
</body>
</html>

内容脚本调用

先确保Offscreen文档已创建,再发送任务:

// 初始化Offscreen文档
async function initOffscreen() {
  if (!(await chrome.offscreen.hasDocument())) {
    await chrome.offscreen.createDocument({
      url: 'offscreen.html',
      reasons: ['DOM_SCRAPING'],
      justification: '执行网页截图OCR识别'
    });
  }
}

// 调用OCR
async function runOcr(screenshot) {
  await initOffscreen();
  return chrome.runtime.sendMessage({
    action: 'runOcr',
    image: screenshot
  });
}

// 使用示例
runOcr('data:image/png;base64,...').then(res => {
  console.log('识别结果:', res.text);
});

3. 预加载隐藏的扩展标签页

创建一个隐藏的扩展标签页作为持久OCR后台,只需初始化一次,后续重复使用:

初始化隐藏标签页(在Service Worker中)

let ocrTabId = null;

async function createHiddenOcrTab() {
  if (!ocrTabId) {
    const tab = await chrome.tabs.create({
      url: chrome.runtime.getURL('ocr-background.html'),
      active: false,
      hidden: true
    });
    ocrTabId = tab.id;
  }
}

// 扩展启动时创建
chrome.runtime.onStartup.addListener(createHiddenOcrTab);
chrome.runtime.onInstalled.addListener(createHiddenOcrTab);

OCR后台页面(ocr-background.html)

逻辑与前两种方案一致,通过消息接收截图数据并执行OCR,此处不再重复代码。

内容脚本调用

直接向隐藏标签页发送消息:

chrome.tabs.sendMessage(ocrTabId, {
  action: 'ocr',
  imageData: screenshotBase64
}, (response) => {
  console.log('识别结果:', response.text);
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 10:05:24