为什么我的 chrome.storage.session 对象从未更新过?

问题描述 投票:0回答:1

我需要一些帮助来改进我的 scraper chrome 扩展。 我尝试总结一下该扩展的作用:

  1. 单击 popup.html 中的按钮,它会打开 10 个选项卡:

popup.js

scrapeRiassunto.addEventListener("click", async () => {

await chrome.storage.session.clear();
let [tab] = await chrome.tabs.query({active:true, currentWindow: true});

chrome.scripting.executeScript({
    target: {tabId: tab.id},
    func: getAllMatches,
    args:[0,from_partita,to_partita,"riassunto"]
});
});
  1. 在我的后台有一个侦听器 chrome.tabs.onUpdated ,它会抓取选项卡中的数据(当状态==完成时),然后以这种方式更新 storage.session :

背景.js

chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
//alert(tab.id + info.url + info.status );
var exUrl = ''
if (changeInfo.status === 'complete' && tab.url.search(/<link>/i) != -1) {
    exUrl = tab.url;
    console.log("executing scraping script");
    chrome.scripting.executeScript({
        target: {tabId: tab.id},
        func: scrapeRiassuntoFromPage,
        // // //func: getAllMatches,
    });
}

函数 scrapeRiassuntoFromPage (在background.js中定义)

//scraping data from tab... and update storage  
chrome.storage.session.get(function(cfg) {
        if(typeof(cfg["riassunti"]) !== 'undefined' && cfg["riassunti"] instanceof Array) { 
            cfg["riassunti"].push(riassuntoEvento);
        } else {
            cfg["riassunti"] = [riassuntoEvento];
        }
        chrome.storage.session.set(cfg); 
    }); chrome.runtime.sendMessage({riassuntoEvento, from: "scrapeRiassuntoFromPage"});

最后,单击 popup.html 中的另一个按钮,我可以访问 chrome.storage.session 对象来检索存储的数据并使用简单的代码创建 CSV:

exportBtn.addEventListener("click", async () => {
if(document.getElementById("linkCSV")){
    document.getElementById("linkCSV").remove();
}

const scrapedData = await chrome.storage.session.get();
//alert(Object.values(scrapedData));
console.log(scrapedData); ...

一切正常,但并非如此!有时我会丢失某些选项卡的某些数据,但我不明白为什么。你有什么建议吗? 谢谢

javascript web-scraping google-chrome-extension
1个回答
0
投票

该问题是由于访问注入代码(函数)中的异步 chrome.storage 引起的,因为它运行在选项卡中,这是一个单独的进程,而且这样的选项卡有很多。当一个选项卡写入存储时,此新数据尚未传播到所有其他选项卡,这些选项卡将自己的值推送到旧数据中,然后写入存储,从而覆盖第一个选项卡的数据。

解决方案是在后台脚本中维护单一事实来源,这将是唯一读取/写入存储的来源。

警告!它不能位于executeScript 中指定的函数或文件内,因为这些函数或文件在与manifest.json 中指定的内容脚本相同的环境中的选项卡中运行。

让我们将 chrome.storage 中的更新数组 MV3 中的维护全局变量 结合起来:

// background.js
let results;
// restoring variables when the background script restarts after dying due to inactivity
let busy = chrome.storage.session.get().then(data => {
  results = data.results || [];
  busy = null;
});

chrome.tabs.onUpdated.addListener(async (tabId, info, tab) => {
  const {url} = tab;
  if (info.status === 'complete' && /<link>/i.test(url)) {
    const [{result}] = await chrome.scripting.executeScript({
      target: {tabId},
      func: scrape,
    });
    if (busy) await busy;
    results.push(...result);
    chrome.storage.session.set({results});
  }
});

async function scrape() {
  let foo = document.querySelector('#foo')?.textContent;
  let bar = document.querySelector('#bar')?.textContent;
  // ...............
  return [
    foo,
    bar,
  ];
}
© www.soinside.com 2019 - 2024. All rights reserved.