Greasy Fork is available in English.
在 1688 详情页提取特定标签图片,去除后缀并批量下载
// ==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);
}
});
})();