淘宝、天猫、阿里巴巴等阿里系电商平台图片打包下载

打包下载主图、视频、SKU、详情页图

目前為 2024-11-14 提交的版本,檢視 最新版本

// ==UserScript==
// @name         淘宝、天猫、阿里巴巴等阿里系电商平台图片打包下载
// @version      2024.11.14
// @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://gf.qytechs.cn/users/786427
// ==/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() {
    //const titleElement = document.querySelector('h1[class*="mainTitle--"], div.title-text');
    Product_Name = document.querySelector('title').textContent;;
  }

  // 获取主视频链接
  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 = `<div style="text-align: center; padding-top: 20px;"><svg t="1729178743032" class="icon" viewBox="0 0 1024 1024" width="32" height="32"><path d="M895.5 831.7H128c-35.1 0-63.8 28.7-63.8 63.8 0 35.1 28.7 63.8 63.8 63.8h767.5c35.1 0 63.8-28.7 63.8-63.8 0-35.1-28.7-63.8-63.8-63.8zM811 383H672.2V123.8c0-33.3-27-60.4-60.4-60.4H412.4c-33.3 0-60.4 27-60.4 60.4V383H213.2c-26.7 0-40.7 31.8-22.5 51.5L489.6 758c12.1 13.1 32.9 13.1 45.1 0l298.8-323.5c18.1-19.7 4.2-51.5-22.5-51.5z" fill="#2196F3"></path></svg></div><p style="color: #2196F3; text-align: center;">下载</p>`;
    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);

})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址