Chrome扩展重开发:动态加载图片从缓存获取方案求助
嘿,这个动态替换图片src的坑我之前踩过好几次!给你几个在Chrome扩展里能落地的解决方案,应该能帮你拿到真实的图片:
方案1:监听DOM变化,捕获真实图片地址
很多网站会把真实图片URL藏在data-src、data-original这类自定义属性里,等页面加载完再动态替换成src。你可以用MutationObserver监听DOM的属性变化和新增元素,直接提取这些真实地址:
// 在content script中编写 const imgObserver = new MutationObserver((mutations) => { mutations.forEach(mutation => { // 处理img元素的src属性变化 if (mutation.type === 'attributes' && mutation.attributeName === 'src') { const img = mutation.target; // 优先取自定义属性里的真实URL,没有再用当前src const realImageUrl = img.dataset.src || img.dataset.original || img.src; console.log('抓到真实图片地址:', realImageUrl); // 这里可以把地址存起来,供后续下载逻辑使用 } // 处理新增的img元素 else if (mutation.type === 'childList') { mutation.addedNodes.forEach(node => { if (node.tagName === 'IMG') { const realImageUrl = node.dataset.src || node.dataset.original || node.src; console.log('新增图片的真实地址:', realImageUrl); } }); } }); }); // 监听整个页面的DOM变化(也可以指定某个特定容器,提升性能) imgObserver.observe(document.body, { childList: true, attributes: true, subtree: true, attributeFilter: ['src'] // 只监听src属性变化,减少不必要的触发 });
方案2:用Chrome扩展的webRequest API拦截图片请求
不管页面怎么动态替换src,只要图片加载了,就一定会发起网络请求。你可以在扩展的后台脚本里用webRequest API拦截所有图片请求,直接拿到真实的请求URL:
首先要在manifest.json里添加必要权限:
{ "permissions": ["webRequest", "webRequestBlocking", "https://你的目标网站域名/*", "storage"] }
然后在后台脚本里编写拦截逻辑:
// background.js中编写 chrome.webRequest.onCompleted.addListener( (details) => { // 只处理图片类型的请求 if (details.type === 'image') { const imageUrl = details.url; // 把图片URL存到chrome.storage里,供content script读取 chrome.storage.local.get('savedImageUrls', (data) => { const urls = data.savedImageUrls || []; if (!urls.includes(imageUrl)) { urls.push(imageUrl); chrome.storage.local.set({ savedImageUrls: urls }); } }); } }, { urls: ["https://你的目标网站域名/*"] }, // 限定只拦截目标网站的请求 [] );
之后你可以在content script里从chrome.storage读取这些URL,实现下载功能。
方案3:直接提取页面上显示的图片内容
如果上面两种方法都拿不到URL,还有个笨但有效的办法:把页面上显示的图片转换成Base64或者Blob直接下载,不管它的src是什么。不过要注意跨域图片的canvas污染问题,这时候需要用扩展权限来绕开:
// 在content script中编写 async function downloadDisplayedImage(imgElement) { try { // 先用canvas绘制图片(如果没有跨域问题的话) const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); canvas.width = imgElement.naturalWidth; canvas.height = imgElement.naturalHeight; ctx.drawImage(imgElement, 0, 0); // 转换成Base64并下载 const dataUrl = canvas.toDataURL('image/png'); const downloadLink = document.createElement('a'); downloadLink.href = dataUrl; downloadLink.download = 'downloaded-image.png'; downloadLink.click(); } catch (err) { // 遇到跨域污染,改用fetch请求(扩展有权限跨域) const response = await fetch(imgElement.src, { credentials: 'include' }); const blob = await response.blob(); const blobUrl = URL.createObjectURL(blob); const downloadLink = document.createElement('a'); downloadLink.href = blobUrl; downloadLink.download = 'downloaded-image.png'; downloadLink.click(); // 用完释放Blob URL URL.revokeObjectURL(blobUrl); } } // 调用示例:比如获取页面上第一个img元素并下载 const targetImg = document.querySelector('img'); if (targetImg) { downloadDisplayedImage(targetImg); }
这三个方案可以根据你的实际场景选择:如果网站用了自定义属性存真实URL,方案1最轻便;如果图片是完全动态加载的,方案2能精准捕获所有图片请求;如果实在拿不到URL,方案3可以直接提取显示的图片内容。
内容的提问来源于stack exchange,提问作者pinguik
相关产品推荐
相关产品推荐

