// ==UserScript== // @name 淘宝详情、天猫详情、阿里巴巴详情,主图、主图视频、SKU图一键打包下载,淘宝链接、天猫链接、阿里巴巴链接精简 // @version 2024.11.14.2 // @description 一键打包下载详情、主图、SKU和视频 // @author Suren_Chan // @match https://detail.tmall.com/* // @match https://item.taobao.com/* // @match https://detail.1688.com/* // @match https://chaoshi.detail.tmall.com/* // @match https://detail.tmall.hk/* // @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 // @grant none // @license MIT // @namespace https://greasyfork.org/users/786427 // @downloadURL none // ==/UserScript== (function() { 'use strict'; // 定义全局变量 let Product_Name = "", Product_Id = new URLSearchParams(window.location.search).get('id') || new URLSearchParams(window.location.search).get('offerId'); const Domain = window.location.protocol + "//" + window.location.hostname; let Main_Video = "", Main_Image = [], SKU_Diagram = [], SKU_Name = [], Details_Page = []; // 清洗页面链接 function CleaningLinks() { const params = new URLSearchParams(window.location.search); const id = params.get('id'); const offerId = params.get('offerId'); const simplifiedUrl = offerId ? `${window.location.origin}/offer/${offerId}.html` : id ? `${window.location.origin}/item.htm?id=${id}` : null; if (simplifiedUrl) { window.history.pushState({}, '', simplifiedUrl); } } CleaningLinks(); // 获取产品名称 function ObtainPN() { // 获取页面的title Product_Name = document.querySelector('title').textContent; // 将title中的“|”替换成“_” Product_Name = Product_Name.replace(/\|/g, '_'); // 现在Product_Name变量中存储的是没有“|”字符,且“|”已被“_”替换的标题 console.log(Product_Name); // 打印处理后的标题,或者进行其他操作 } // 获取主视频链接 function ObtainMV() { const videoElement = document.querySelector('.lib-video video'); if (videoElement) Main_Video = videoElement.src.split('?')[0]; } // 获取图片 URL 并清洗 const cleanImageUrl = (url) => url.replace(/(\.jpg|\.jpeg|\.png|\.gif)(.*)?$/, '$1'); // 获取主图 function ObtainMI() { document.querySelectorAll('ul[class*="thumbnails--"], div.img-list-wrapper').forEach(element => { element.querySelectorAll('img').forEach(img => Main_Image.push(cleanImageUrl(img.src))); }); } // 获取 SKU 图 function ObtainSD() { document.querySelectorAll('img[class*="valueItemImg--"], div.sku-item-image').forEach(element => { let imageUrl = element.tagName === 'IMG' ? cleanImageUrl(element.src) : cleanImageUrl(element.style.backgroundImage?.match(/url\(["']?([^"']+)["']?\)/)?.[1]); if (imageUrl) SKU_Diagram.push(imageUrl); }); } // 获取 SKU 名称并处理字符 function ObtainSN() { document.querySelectorAll('span[class*="valueItemText--"], div.sku-item-name').forEach(el => { const replacedText = el.textContent.trim().replace(/\//g, '每').replace(/\*/g, 'x'); SKU_Name.push(replacedText); }); } // 获取详情页图 function ObtainDP() { const contentDiv = document.querySelector('.desc-root') || document.querySelector('.content-detail'); if (contentDiv) { contentDiv.querySelectorAll('img').forEach(img => { let src = img.src.split('?')[0]; if (img.width >= 700 && src.match(/\.(jpg|jpeg|png|gif)$/)) Details_Page.push(src); }); } } // 创建下载按钮 function createDownloadButton() { const button = document.createElement('div'); button.style.cssText = 'position: fixed; width: 56px; height: 90px; background-color: #fff; right: 0px; top: 300px; z-index: 9999; border-radius: 18px 0 0 18px; box-shadow: -2px 0 30px 2px rgba(97, 105, 119, 0.18); cursor: pointer;'; button.innerHTML = `

下载

`; document.body.appendChild(button); return button; } // 创建进度条容器 function createProgressBar() { const container = document.createElement('div'); container.style.cssText = 'position: fixed; width:500px; top: 50%; left: 50%; transform: translate(-50%, -50%); background-color: rgba(0, 0, 0, 0.7); padding: 20px; border-radius: 10px; z-index: 9999; display: none;'; const progressBar = document.createElement('div'); progressBar.style.cssText = 'width: 100%; background-color: #ddd; border-radius: 5px; position: relative;'; const progressFill = document.createElement('div'); progressFill.style.cssText = 'width: 0%; height: 20px; background-color: #2196f3; border-radius: 5px;'; const progressText = document.createElement('span'); progressText.textContent = '正在下载……'; // 设置文字内容 progressText.style.cssText = 'position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: #2196f3; font-family: "微软雅黑"; font-size: 18px; text-shadow: 1px 1px 0px #fff, -1px -1px 0px #fff, 1px -1px 0px #fff, -1px 1px 0px #fff;'; // 设置样式,添加白色描边 progressBar.appendChild(progressFill); progressBar.appendChild(progressText); // 将文字添加到进度条容器中 container.appendChild(progressBar); document.body.appendChild(container); return { container, progressFill }; } // 下载并打包所有图片 async function downloadImages() { const { container, progressFill } = createProgressBar(); container.style.display = 'block'; progressFill.style.width = '0%'; const zip = new JSZip(); const mainFolder = zip.folder("主图"); const skuFolder = zip.folder("SKU"); const slicesFolder = zip.folder("切片"); progressFill.style.width = '5%'; // 获取所有资源 ObtainPN(); ObtainMV(); ObtainMI(); ObtainSD(); ObtainSN(); ObtainDP(); progressFill.style.width = '10%'; // 处理主视频 if (Main_Video) { const videoBlob = await fetch(Main_Video).then(res => res.blob()); mainFolder.file("主图视频.mp4", videoBlob); progressFill.style.width = '20%'; } // 处理主图 for (let i = 0; i < Main_Image.length; i++) { const imgBlob = await fetch(Main_Image[i]).then(res => res.blob()); mainFolder.file(`主图${i + 1}.${Main_Image[i].split('.').pop()}`, imgBlob); progressFill.style.width = '30%'; } // 处理 SKU 图 for (let i = 0; i < SKU_Diagram.length; i++) { const imgBlob = await fetch(SKU_Diagram[i]).then(res => res.blob()); const fileExtension = SKU_Diagram[i].split('.').pop(); const fileName = SKU_Diagram.length === SKU_Name.length ? `${SKU_Name[i]}.${fileExtension}` : `SKU${(i + 1).toString().padStart(2, '0')}.${fileExtension}`; skuFolder.file(fileName, imgBlob); progressFill.style.width = '40%'; } // 处理详情图 for (let i = 0; i < Details_Page.length; i++) { const imgBlob = await fetch(Details_Page[i]).then(res => res.blob()); const paddedIndex = (i + 1).toString().padStart(2, '0'); const fileName = `image${paddedIndex}`; const fileExtension = Details_Page[i].split('.').pop(); slicesFolder.file(`${fileName}.${fileExtension}`, imgBlob); progressFill.style.width = '50%'; } // 拼接长图并添加 const longCanvas = document.createElement('canvas'); longCanvas.width = 790; let totalHeight = 0; const imagesForLongImg = []; for (const imgSrc of Details_Page) { const img = await createImageBitmap(await fetch(imgSrc).then(res => res.blob())); imagesForLongImg.push(img); totalHeight += img.height * (790 / img.width); progressFill.style.width = '70%'; } longCanvas.height = totalHeight; const ctx = longCanvas.getContext('2d'); let currentHeight = 0; for (const img of imagesForLongImg) { ctx.drawImage(img, 0, currentHeight, 790, img.height * (790 / img.width)); currentHeight += img.height * (790 / img.width); progressFill.style.width = '80%'; } const longImgBlob = await new Promise(resolve => longCanvas.toBlob(resolve, "image/png")); zip.file(`${Product_Name}.png`, longImgBlob); progressFill.style.width = '90%'; // 生成并保存 ZIP 文件 const zipContent = await zip.generateAsync({ type: "blob" }); saveAs(zipContent, `${Product_Name}.zip`); progressFill.style.width = '100%'; container.style.display = 'none'; } // 创建下载按钮和触发下载过程 const downloadButton = createDownloadButton(); downloadButton.addEventListener('click', downloadImages); })();