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

Chrome扩展开发:如何在contentScript中运行JavaScript版Selenium?

问题分析与解决方案

首先明确核心限制:Chrome扩展的Content Script无法直接使用Selenium——Selenium是基于Node.js的外部自动化工具,运行在浏览器进程之外;而Content Script是在浏览器页面上下文内执行的前端JavaScript,两者运行环境完全隔离,无法直接兼容。

以下是适配Chrome扩展生态的替代方案,实现跨购物网站的商品数据采集:


一、修改Manifest.json(Manifest V3 版本)

需要配置必要的扩展权限,允许跨站访问、标签页操作、脚本注入及数据存储:

{
  "manifest_version": 3,
  "name": "商品价格采集工具",
  "version": "1.0",
  "permissions": ["storage", "tabs", "scripting"],
  "host_permissions": ["<all_urls>"],
  "content_scripts": [
    {
      "matches": ["*://*.amazon.com.tr/*"],
      "js": ["contentScript.js"]
    }
  ],
  "background": {
    "service_worker": "background.js"
  },
  "action": {
    "default_popup": "popup.html"
  }
}

二、重构代码逻辑

1. Content Script(contentScript.js)

负责在亚马逊页面采集基础数据,并向后台发起跨站数据采集请求:

// 初始化已存储的商品列表
let allProducts = [];
chrome.storage.sync.get('products', (result) => {
  if (result.products) allProducts = JSON.parse(result.products);
});

const addProductImageTest = async () => {  
  // 采集亚马逊页面数据
  const newProduct = {
    productImage: document.getElementById("landingImage").src,
    productPrice: document.getElementsByClassName("a-price aok-align-center")[0].children[0].innerText,
    productAvailability: document.getElementById("availability").children[0].innerText,
    productName: document.getElementById("productTitle").innerText.trim(),   
    otherPrices: {}
  };

  // 请求后台采集其他网站的同款商品价格
  const otherSitePrices = await chrome.runtime.sendMessage({
    type: "FETCH_OTHER_SITE_PRICES",
    productName: newProduct.productName
  });

  // 合并跨站数据
  if (otherSitePrices) newProduct.otherPrices = otherSitePrices;

  // 存储到浏览器同步存储
  allProducts.push(newProduct);
  chrome.storage.sync.set({ products: JSON.stringify(allProducts) });
};

// 绑定页面触发按钮(需自行添加页面按钮元素)
document.querySelector('#collect-btn')?.addEventListener('click', addProductImageTest);

2. Background Service Worker(background.js)

作为扩展的后台逻辑核心,负责打开目标购物网站、注入脚本采集数据:

chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => {
  if (request.type === "FETCH_OTHER_SITE_PRICES") {
    const productName = request.productName;
    const collectedPrices = {};

    // 示例:采集n11.com的商品价格
    try {
      // 创建后台标签页访问目标网站
      const tab = await chrome.tabs.create({
        url: `https://www.n11.com/arama?q=${encodeURIComponent(productName)}`,
        active: false
      });

      // 等待标签页加载完成
      await new Promise(resolve => {
        const loadListener = (tabId, changeInfo) => {
          if (tabId === tab.id && changeInfo.status === 'complete') {
            chrome.tabs.onUpdated.removeListener(loadListener);
            resolve();
          }
        };
        chrome.tabs.onUpdated.addListener(loadListener);
      });

      // 注入脚本采集价格数据
      const [priceResult] = await chrome.scripting.executeScript({
        target: { tabId: tab.id },
        func: () => {
          // 适配目标网站的DOM选择器
          const priceElem = document.querySelector('.newPrice');
          return priceElem ? priceElem.innerText : '未找到价格';
        }
      });

      collectedPrices.n11 = priceResult.result;
      // 关闭临时标签页
      await chrome.tabs.remove(tab.id);
    } catch (err) {
      collectedPrices.n11 = '采集失败';
      console.error('n11采集出错:', err);
    }

    // 可重复上述逻辑,添加更多购物网站的采集代码...

    sendResponse(collectedPrices);
  }
  return true; // 告知Chrome等待异步响应
});

三、关键说明

  1. 跨域问题解决:通过Background Service Worker的标签页操作+脚本注入,绕过了Content Script的跨域限制,合法访问其他购物网站。
  2. 替代Selenium的核心逻辑:用Chrome扩展原生的tabs和scripting API,实现了Selenium的"打开页面-定位元素-提取数据"核心流程,完全适配扩展生态。
  3. Manifest V3 注意事项:必须使用Service Worker替代旧版Background Page,所有异步操作需遵循Promise/async-await规范。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 13:13:21