Greasy Fork

Greasy Fork is available in English.

1688 详情页图片批量下载

在 1688 详情页提取特定标签图片,去除后缀并批量下载

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         1688 详情页图片批量下载
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  在 1688 详情页提取特定标签图片,去除后缀并批量下载
// @author       Gemini & Charon2050
// @match        *://detail.1688.com/*
// @grant        GM_download
// @license      Unlicense
// ==/UserScript==

(function() {
    'use strict';

    // 1. 创建悬浮按钮
    const btn = document.createElement('button');
    btn.innerText = '📦 下载图片';
    btn.style.position = 'fixed';
    btn.style.bottom = '100px';
    btn.style.right = '50px';
    btn.style.zIndex = '999999';
    btn.style.padding = '12px 24px';
    btn.style.backgroundColor = '#ff6000'; // 1688 主题色
    btn.style.color = '#fff';
    btn.style.border = 'none';
    btn.style.borderRadius = '8px';
    btn.style.cursor = 'pointer';
    btn.style.boxShadow = '0 4px 12px rgba(255, 96, 0, 0.4)';
    btn.style.fontSize = '16px';
    btn.style.fontWeight = 'bold';
    btn.style.transition = 'all 0.3s';

    // 悬停效果
    btn.onmouseover = () => {
        btn.style.backgroundColor = '#e55600';
        btn.style.transform = 'translateY(-2px)';
    };
    btn.onmouseout = () => {
        btn.style.backgroundColor = '#ff6000';
        btn.style.transform = 'translateY(0)';
    };

    document.body.appendChild(btn);

    // 2. 点击事件逻辑
    btn.addEventListener('click', () => {
        const urlSet = new Set(); // 使用 Set 去重

        // --- 目标一:处理 span.v-image-cover ---
        const covers = document.querySelectorAll('span.v-image-cover');
        covers.forEach(el => {
            const bgImage = el.style.backgroundImage;
            if (bgImage) {
                // 提取 url("...") 中的链接
                const match = bgImage.match(/url\(['"]?(.*?)['"]?\)/);
                if (match && match[1]) {
                    let url = match[1];
                    // 去除末尾的 _b.jpg
                    url = url.replace(/_b\.jpg$/i, '');
                    urlSet.add(url);
                }
            }
        });

        // --- 目标二:处理 div.item-image-icon 内的 img.ant-image-img ---
        const imgs = document.querySelectorAll('div.ant-image.v-image-wrap.item-image-icon img.ant-image-img');
        imgs.forEach(el => {
            let url = el.src;
            if (url) {
                // 去除末尾的 _sum.jpg
                url = url.replace(/_sum\.jpg$/i, '');
                urlSet.add(url);
            }
        });

        // 检查是否有获取到图片
        if (urlSet.size === 0) {
            alert('当前页面未找到符合条件的图片!请确保页面已完全加载。');
            return;
        }

        // --- 开始批量下载 ---
        btn.innerText = `⏳ 准备下载 (${urlSet.size}张)`;
        btn.style.backgroundColor = '#999';
        btn.disabled = true;

        let downloadedCount = 0;

        urlSet.forEach(url => {
            // 补全协议头 (处理 //cbu01... 这种格式)
            if (url.startsWith('//')) {
                url = location.protocol + url;
            }

            // 从 URL 中截取文件名作为下载保存的文件名
            let filename = url.substring(url.lastIndexOf('/') + 1);
            filename = filename.split('?')[0]; // 去除 URL 参数

            // 使用油猴 API 触发下载
            GM_download({
                url: url,
                name: filename,
                onload: () => {
                    downloadedCount++;
                    btn.innerText = `⏳ 下载中 (${downloadedCount}/${urlSet.size})`;
                    if (downloadedCount === urlSet.size) {
                        resetButton();
                    }
                },
                onerror: (err) => {
                    console.error('图片下载失败:', url, err);
                    downloadedCount++; // 即使失败也推进计数,防止按钮卡死
                    if (downloadedCount === urlSet.size) {
                        resetButton();
                    }
                }
            });
        });

        // 恢复按钮状态的函数
        function resetButton() {
            setTimeout(() => {
                btn.innerText = '✅ 下载完成';
                btn.style.backgroundColor = '#52c41a';
                setTimeout(() => {
                    btn.innerText = '📦 下载图片';
                    btn.style.backgroundColor = '#ff6000';
                    btn.disabled = false;
                }, 2000);
            }, 500);
        }
    });
})();