我需要一些帮助来改进我的 scraper chrome 扩展。 我尝试总结一下该扩展的作用:
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"]
});
});
背景.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); ...
一切正常,但并非如此!有时我会丢失某些选项卡的某些数据,但我不明白为什么。你有什么建议吗? 谢谢
该问题是由于访问注入代码(函数)中的异步 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,
];
}