如何用JavaScript/Tampermonkey提取图片链接的点击事件目标URL?
解决思路与实现方案
方案1:Hook window.open 捕获图片URL
论坛的点击逻辑大概率是通过window.open(image_url)打开图片,我们可以重写这个方法来拦截并提取目标URL:
// 保存原生window.open方法 const originalOpen = window.open; window.open = function(url, ...args) { // 根据论坛图片URL特征判断(可自行调整后缀匹配规则) if (url && /\.(jpg|jpeg|png|gif|webp)$/i.test(url)) { // 定位触发点击的目标链接 const targetLink = document.activeElement; if (targetLink.tagName === 'A' && targetLink.title === 'image') { // 创建img标签替换原链接 const img = document.createElement('img'); img.src = url; img.style.maxWidth = '100%'; // 适配帖子宽度 targetLink.replaceWith(img); } // 阻止默认打开新标签的行为 return null; } // 非图片链接调用原生方法 return originalOpen.apply(window, [url, ...args]); }; // 给已存在的图片链接绑定点击监听,确保hook生效 document.querySelectorAll('a[title="image"]').forEach(link => { link.addEventListener('click', () => {}, { once: true }); });
方案2:拦截点击事件,捕获跳转URL
如果论坛不用window.open,而是通过修改location.href跳转,可通过拦截点击并临时劫持location.href来获取URL:
document.querySelectorAll('a[title="image"]').forEach(link => { link.addEventListener('click', async (e) => { e.preventDefault(); e.stopPropagation(); // 临时替换location.href的setter const originalLocation = Object.getOwnPropertyDescriptor(window.location, 'href'); let imageUrl = null; Object.defineProperty(window.location, 'href', { get: () => originalLocation.get.call(window.location), set: function(url) { if (/\.(jpg|jpeg|png|gif|webp)$/i.test(url)) { imageUrl = url; } else { originalLocation.set.call(this, url); } }, configurable: true }); // 触发论坛原生点击事件 const clickEvent = new MouseEvent('click', { bubbles: true, cancelable: true }); link.dispatchEvent(clickEvent); // 恢复原生location.href Object.defineProperty(window.location, 'href', originalLocation); // 替换为img标签 if (imageUrl) { const img = document.createElement('img'); img.src = imageUrl; img.style.maxWidth = '100%'; link.replaceWith(img); } }, { once: true }); });
方案3:尝试提取元素绑定的事件监听器(兼容性有限)
Chrome等浏览器的getEventListeners是DevTools专属API,需注入脚本到页面上下文才能调用,且依赖论坛代码结构:
// 注入到页面上下文的脚本 function extractImageUrls() { document.querySelectorAll('a[title="image"]').forEach(link => { const listeners = getEventListeners(link); if (listeners?.click) { listeners.click.forEach(listener => { // 从事件处理函数的字符串中匹配图片URL const funcStr = listener.listener.toString(); const urlMatch = funcStr.match(/https?:\/\/.*?\.(jpg|jpeg|png|gif|webp)/i); if (urlMatch) { const img = document.createElement('img'); img.src = urlMatch[0]; img.style.maxWidth = '100%'; link.replaceWith(img); } }); } }); } // 注入脚本执行 const script = document.createElement('script'); script.textContent = `(${extractImageUrls.toString()})();`; document.body.appendChild(script); script.remove();
注意:方案3兼容性最差,论坛代码更新后容易失效,优先推荐方案1和方案2。
内容的提问来源于stack exchange,提问作者jm92
相关产品推荐
相关产品推荐

