Chrome 扩展程序,用于修改无法加载的图片

Chrome Extension to modify images that fail to load

本文关键字:加载 修改 扩展 程序 用于 Chrome      更新时间:2023-09-26

我去过一个网站,那里有有用的旧页面,但图像在他们的网站上消失了。对我来说幸运的是,我碰巧有一堆这样的图像,因为我保留了它们的副本。所以,我很容易一一看这些图像。但是,这就是我想做的:

我想编写一个 Chrome 扩展程序,该扩展程序将以某种方式找到任何无法加载的图像,并将它们替换为我将打包在扩展程序中的图像。

因此,例如,如果原始图像http://broken.site/whatever1/whatever2/whatever3/missing.jpg(并且确实出错),我希望将其替换为扩展中的missing.jpg

不希望它从我将提供的缓存中加载该站点的所有图像,只加载那些错误的图像。有没有简单的方法可以做到这一点?

我可以看到如何通过以下方式获取所有图像:

imgs = document.getElementsByTagName("img")

imgs[0].src似乎给了我URL,这很酷。但是imgs[0].complete说完成,无论它是否成功检索图像。有没有办法确定特定图像是否确实加载了?

您可以使用

API 捕获和重定向服务器使用 404 回复的请求webRequest

这样,您可以在后台脚本中执行此操作,并且不需要内容脚本来分析带有document.getElementsByTagName("img")的页面,请求将被"传输中"拦截。

function isMissing(line) {
  return !!(line.match(/^[^ ]* 404/));
}
chrome.webRequest.onHeadersReceived.addListener(
  function(details) {
    if(isMissing(details.statusLine)) {
      var fixedURL;
      /* TODO: Assign fixedURL based on details.url */
      // If the image is in the extension, use
      //   chrome.runtime.getURL("filename.jpg")
      return {redirectUrl: fixedURL};
    }
  },
  {
    // Tailor this filter for your site
    urls: ["*://*.example.com/*"],
    types: ["image"]
  },
  ["blocking"]
);

您将需要主机权限(例如 "*://*.example.com/*"),"webRequest""webRequestBlocking"

我构建了扩展图像回退,这听起来与您尝试实现的目标非常相似。

您可以在 github 上查看扩展的源代码。我在下面的代码库中添加了几个相关的片段。

下面是后台脚本中的代码,用于侦听加载失败的图像。然后,它会向内容脚本发送一条消息,其中包含需要替换的图像。

/**
 * Stores messages for each tab keyed by tabId
 *
 * These will be used if an image errors before the content script has loaded 
 */
var tabMessages = {};
/**
 * Listen to all responses for images
 * 
 * If the status code is 404 and the host have a fallback url configured notify the content script
 */
chrome.webRequest.onCompleted.addListener(function(e) {
  // Ignore responses if the status code was not a 404 or 500 
  if (!e.statusCode || (e.statusCode !== 404 && e.statusCode !== 500)) {
    return;
  }
  var message = {
    target: targetImage,
    fallback: fallbackUrl
  };
  // Send a message to the content script for this tab
  chrome.tabs.sendMessage(e.tabId, message, function(response) {
    if (typeof response === 'undefined') {
      // The content script probably hasn't loaded yet
      // Add fallback to the message queue for this tab
      // Instead the content script must request image replacements once it is loaded
      tabMessages[e.tabId].push(message);
    }
  });
}, {
  urls: ['<all_urls>'],
  types: ['image']
}, ['responseHeaders']);

这是侦听来自后台脚本的消息,然后交换图像的内容脚本。

/**
 * Request any images that have errored before this script was loaded from the background script.
 */
chrome.runtime.sendMessage({
  action: 'getImageFallbacks'
}, function(response) {
  if (!response || !response.length) {
    return;
  }
  response.forEach(function(replace) {
    // Replace the images with your fallback
    $('[src$="'+ replace.target +'"]').attr('src', replace.fallback);
  });
});
/**
 * Listen for image replacement requests sent from the background script
 */
chrome.runtime.onMessage.addListener(function(replace, sender, sendResponse) {
  // Replace the images with your fallback
  $('[src$="'+ replace.target +'"]').attr('src', replace.fallback);
  // Send a response to the background script so it knows we have replaced this image
  sendResponse({
    success: true
  });
});

您还需要在 manifest.json 中遵循以下权限:

"permissions": ["<all_urls>", "webRequest","webRequestBlocking", "tabs", "storage"]