// ==UserScript== // @name 淘宝天猫图片打包下载 // @version 2024.11.12 // @description 主图、SKU、详情和视频打包下载 // @author Suren_Chan // @match https://detail.tmall.com/* // @match https://item.taobao.com/* // @match https://item.taobao.com/item.htm?* // @match https://detail.tmall.com/item.htm?* // @description 下载页面中的图片并打包为 ZIP 文件,生成整版详情长图和调整图片宽度为 790px 的独立图片文件集一起下载。 // @author Suren_Chan // @require https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js // @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw== // @grant none // @license MIT // @namespace https://greasyfork.org/users/786427 // @downloadURL none // ==/UserScript== (function() { 'use strict'; // 创建进度条容器 const progressContainer = document.createElement('div'); progressContainer.style.position = 'fixed'; progressContainer.style.top = '50%'; progressContainer.style.left = '50%'; progressContainer.style.transform = 'translate(-50%, -50%)'; progressContainer.style.backgroundColor = 'rgba(0, 0, 0, 0.7)'; progressContainer.style.color = '#fff'; progressContainer.style.padding = '20px'; progressContainer.style.borderRadius = '10px'; progressContainer.style.zIndex = '9999'; progressContainer.style.display = 'none'; // 默认隐藏 // 创建进度条 const progressBar = document.createElement('div'); progressBar.style.width = '100%'; progressBar.style.backgroundColor = '#ddd'; progressBar.style.borderRadius = '5px'; const progressFill = document.createElement('div'); progressFill.style.width = '0%'; progressFill.style.height = '20px'; progressFill.style.backgroundColor = '#4caf50'; progressFill.style.borderRadius = '5px'; progressBar.appendChild(progressFill); progressContainer.appendChild(progressBar); document.body.appendChild(progressContainer); // 创建外部 div const customDiv = document.createElement('div'); customDiv.style.position = 'fixed'; customDiv.style.width = '56px'; customDiv.style.height = '90px'; customDiv.style.backgroundColor = '#fff'; customDiv.style.right = '0px'; customDiv.style.top = '300px'; customDiv.style.zIndex = '9999'; customDiv.style.borderRadius = '18px 0 0 18px'; customDiv.style.boxShadow = '-2px 0 30px 2px rgba(97, 105, 119, 0.18)'; customDiv.style.cursor = 'pointer'; // 创建包含 SVG 的 div const svgContainer = document.createElement('div'); svgContainer.style.textAlign = 'center'; svgContainer.style.paddingTop = '20px'; // 创建 SVG const svgIcon = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); svgIcon.setAttribute('width', '32'); svgIcon.setAttribute('height', '32'); svgIcon.innerHTML = ``; svgContainer.appendChild(svgIcon); // 创建 p 标签并设置文本和样式 const pTag = document.createElement('p'); pTag.textContent = '下载'; pTag.style.color = '#2196F3'; pTag.style.textAlign = 'center'; customDiv.appendChild(svgContainer); customDiv.appendChild(pTag); // 添加点击事件 customDiv.addEventListener('click', async function() { // 显示进度条 progressContainer.style.display = 'block'; progressFill.style.width = '0%'; // 重置进度条 // 获取 id 为 content 的 div const contentDiv = document.getElementById('content'); if (!contentDiv) { alert('未找到指定的 div!'); progressContainer.style.display = 'none'; // 隐藏进度条 return; } // 获取所有 img 标签 const images = contentDiv.getElementsByTagName('img'); const imageUrls = []; let totalHeight = 0; // 创建一个 JSZip 实例 const zip = new JSZip(); const slicesFolder = zip.folder('切片'); // 创建“切片”文件夹 // 加载和调整图片 const resizedImages = await Promise.all(Array.from(images).map(async (img, index) => { const imgSrc = img.src; const imgExt = imgSrc.match(/\.(jpg|jpeg|png|gif)$/i)?.[0] || '.jpg'; const response = await fetch(imgSrc); const blob = await response.blob(); const bitmap = await createImageBitmap(blob); // 计算新的高度等比缩放 const newHeight = Math.floor(bitmap.height * (790 / bitmap.width)); totalHeight += newHeight; // 创建 canvas 调整图片大小 const canvas = document.createElement('canvas'); canvas.width = 790; canvas.height = newHeight; const ctx = canvas.getContext('2d'); ctx.drawImage(bitmap, 0, 0, 790, newHeight); // 将调整后的图像添加到 ZIP 文件的 "切片" 文件夹 const imgBlob = await new Promise((resolve) => canvas.toBlob(resolve, `image/${imgExt.replace('.', '')}`)); slicesFolder.file(`image${String(index + 1).padStart(2, '0')}${imgExt}`, imgBlob); // 返回 canvas,用于拼接整版图片 return canvas; })); // 拼接所有调整后的图片成一张长图 const fullCanvas = document.createElement('canvas'); fullCanvas.width = 790; fullCanvas.height = totalHeight; const fullCtx = fullCanvas.getContext('2d'); let currentHeight = 0; for (const canvas of resizedImages) { fullCtx.drawImage(canvas, 0, currentHeight); currentHeight += canvas.height; } // 将整版长图转换为 PNG 并添加到 ZIP 文件 const fullBlob = await new Promise((resolve) => fullCanvas.toBlob(resolve, 'image/png')); zip.file('整版详情.png', fullBlob); // 更新进度条到完成 progressFill.style.width = '100%'; // 生成 ZIP 文件并下载 zip.generateAsync({ type: 'blob' }) .then(function(content) { saveAs(content, 'images.zip'); // 使用 FileSaver.js 下载 ZIP progressContainer.style.display = 'none'; // 隐藏进度条 }); }); // 将 div 添加到页面 document.body.appendChild(customDiv); })();