Greasy Fork

Greasy Fork is available in English.

批量图片提取与下载

提取图片后支持全选、取消全选、一键下载全部图片和下载选中图片为 ZIP 文件,UI 美化版,带链接输入界面。

当前为 2025-01-06 提交的版本,查看 最新版本

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         批量图片提取与下载
// @namespace    http://tampermonkey.net/
// @version      1.4.3
// @description  提取图片后支持全选、取消全选、一键下载全部图片和下载选中图片为 ZIP 文件,UI 美化版,带链接输入界面。
// @author       vicwang
// @match        *://*/*
// @grant        none
// @require      https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js
// @license MIT
// ==/UserScript==

(function () {
    'use strict';

    // 创建“开始”按钮
    const startButton = document.createElement('button');
    startButton.textContent = '开始';
    startButton.style.position = 'fixed';
    startButton.style.top = '10px';
    startButton.style.right = '10px';
    startButton.style.zIndex = '9999';
    startButton.style.padding = '10px 20px';
    startButton.style.backgroundColor = '#007BFF';
    startButton.style.color = '#fff';
    startButton.style.border = 'none';
    startButton.style.borderRadius = '8px';
    startButton.style.cursor = 'pointer';
    startButton.style.boxShadow = '0 4px 6px rgba(0, 0, 0, 0.1)';
    startButton.style.fontSize = '14px';
    startButton.style.fontWeight = '500';
    startButton.style.transition = 'background-color 0.3s ease';
    document.body.appendChild(startButton);

    // 按钮悬停效果
    startButton.addEventListener('mouseenter', () => {
        startButton.style.backgroundColor = '#0056b3';
    });
    startButton.addEventListener('mouseleave', () => {
        startButton.style.backgroundColor = '#007BFF';
    });

    // 点击“开始”按钮
    startButton.addEventListener('click', () => {
        // 创建模态对话框
        const modal = document.createElement('div');
        modal.style.position = 'fixed';
        modal.style.top = '0';
        modal.style.left = '0';
        modal.style.width = '100%';
        modal.style.height = '100%';
        modal.style.backgroundColor = 'rgba(0, 0, 0, 0.8)';
        modal.style.zIndex = '10000';
        modal.style.display = 'flex';
        modal.style.justifyContent = 'center';
        modal.style.alignItems = 'center';
        document.body.appendChild(modal);

        // 创建对话框内容
        const dialog = document.createElement('div');
        dialog.style.backgroundColor = '#fff';
        dialog.style.padding = '20px';
        dialog.style.borderRadius = '10px';
        dialog.style.boxShadow = '0 4px 10px rgba(0, 0, 0, 0.2)';
        dialog.style.width = '400px';
        dialog.style.maxWidth = '90%';
        modal.appendChild(dialog);

        // 创建标题
        const title = document.createElement('h3');
        title.textContent = '请输入图片链接';
        title.style.marginTop = '0';
        title.style.fontSize = '18px';
        title.style.color = '#333';
        dialog.appendChild(title);

        // 创建输入框
        const inputBox = document.createElement('textarea');
        inputBox.placeholder = '每行一个链接';
        inputBox.style.width = '100%';
        inputBox.style.height = '150px';
        inputBox.style.padding = '10px';
        inputBox.style.border = '1px solid #ccc';
        inputBox.style.borderRadius = '5px';
        inputBox.style.fontSize = '14px';
        inputBox.style.marginBottom = '15px';
        inputBox.style.boxSizing = 'border-box';
        dialog.appendChild(inputBox);

        // 创建按钮容器
        const buttonContainer = document.createElement('div');
        buttonContainer.style.display = 'flex';
        buttonContainer.style.justifyContent = 'flex-end';
        buttonContainer.style.gap = '10px';
        dialog.appendChild(buttonContainer);

        // 创建确认按钮
        const confirmButton = document.createElement('button');
        confirmButton.textContent = '确认';
        confirmButton.style.padding = '8px 16px';
        confirmButton.style.backgroundColor = '#28A745';
        confirmButton.style.color = '#fff';
        confirmButton.style.border = 'none';
        confirmButton.style.borderRadius = '5px';
        confirmButton.style.cursor = 'pointer';
        confirmButton.style.fontSize = '14px';
        confirmButton.style.transition = 'background-color 0.3s ease';
        buttonContainer.appendChild(confirmButton);

        // 确认按钮悬停效果
        confirmButton.addEventListener('mouseenter', () => {
            confirmButton.style.backgroundColor = '#218838';
        });
        confirmButton.addEventListener('mouseleave', () => {
            confirmButton.style.backgroundColor = '#28A745';
        });

        // 创建取消按钮
        const cancelButton = document.createElement('button');
        cancelButton.textContent = '取消';
        cancelButton.style.padding = '8px 16px';
        cancelButton.style.backgroundColor = '#FF4C4C';
        cancelButton.style.color = '#fff';
        cancelButton.style.border = 'none';
        cancelButton.style.borderRadius = '5px';
        cancelButton.style.cursor = 'pointer';
        cancelButton.style.fontSize = '14px';
        cancelButton.style.transition = 'background-color 0.3s ease';
        buttonContainer.appendChild(cancelButton);

        // 取消按钮悬停效果
        cancelButton.addEventListener('mouseenter', () => {
            cancelButton.style.backgroundColor = '#cc0000';
        });
        cancelButton.addEventListener('mouseleave', () => {
            cancelButton.style.backgroundColor = '#FF4C4C';
        });

        // 确认按钮点击事件
        confirmButton.addEventListener('click', () => {
            const links = inputBox.value.split('\n').map(link => link.trim()).filter(link => link);
            if (links.length === 0) {
                alert('请输入至少一个有效链接');
                return;
            }
            modal.remove(); // 关闭对话框
            processLinks(links); // 处理链接
        });

        // 取消按钮点击事件
        cancelButton.addEventListener('click', () => {
            modal.remove(); // 关闭对话框
        });
    });

    // 处理链接
    function processLinks(links) {
        // 创建图片展示容器
        const container = document.createElement('div');
        container.style.position = 'fixed';
        container.style.top = '0';
        container.style.left = '0';
        container.style.width = '100%';
        container.style.height = '100%';
        container.style.backgroundColor = 'rgba(0, 0, 0, 0.95)';
        container.style.overflowY = 'scroll';
        container.style.zIndex = '10000';
        container.style.display = 'flex';
        container.style.flexWrap = 'wrap';
        container.style.gap = '15px';
        container.style.padding = '20px';
        container.style.boxSizing = 'border-box';
        document.body.appendChild(container);

        // 创建关闭按钮
        const closeButton = document.createElement('button');
        closeButton.textContent = '关闭';
        closeButton.style.position = 'fixed';
        closeButton.style.top = '20px';
        closeButton.style.right = '20px';
        closeButton.style.zIndex = '10001';
        closeButton.style.padding = '10px 20px';
        closeButton.style.backgroundColor = '#FF4C4C';
        closeButton.style.color = '#fff';
        closeButton.style.border = 'none';
        closeButton.style.borderRadius = '8px';
        closeButton.style.cursor = 'pointer';
        closeButton.style.boxShadow = '0 4px 6px rgba(0, 0, 0, 0.1)';
        closeButton.style.fontSize = '14px';
        closeButton.style.fontWeight = '500';
        closeButton.style.transition = 'background-color 0.3s ease';
        container.appendChild(closeButton);

        // 关闭按钮悬停效果
        closeButton.addEventListener('mouseenter', () => {
            closeButton.style.backgroundColor = '#cc0000';
        });
        closeButton.addEventListener('mouseleave', () => {
            closeButton.style.backgroundColor = '#FF4C4C';
        });

        closeButton.addEventListener('click', () => {
            container.remove();
        });

        // 图片列表
        const imageList = [];
        const selectedImages = new Set(); // 记录选中的图片

        // 检查链接是否为图片
        const isImageLink = (url) => {
            return /\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i.test(url);
        };

        // 提取每个链接中的图片
        const promises = links.map(link => {
            if (isImageLink(link)) {
                imageList.push(link);
                return Promise.resolve();
            } else {
                return fetch(link)
                    .then(response => response.text())
                    .then(html => {
                        const tempDiv = document.createElement('div');
                        tempDiv.innerHTML = html;
                        const images = Array.from(tempDiv.querySelectorAll('img')).map(img => img.src);
                        imageList.push(...images);
                    })
                    .catch(() => console.error(`无法加载链接:${link}`));
            }
        });

        // 等待所有提取完成
        Promise.all(promises).then(() => {
            if (imageList.length === 0) {
                alert('未找到任何图片');
                return;
            }

            // 显示所有图片
            const imageElements = [];
            imageList.forEach((src, index) => {
                const imgWrapper = document.createElement('div');
                imgWrapper.style.flex = '1 1 calc(25% - 15px)';
                imgWrapper.style.display = 'flex';
                imgWrapper.style.alignItems = 'center';
                imgWrapper.style.justifyContent = 'center';
                imgWrapper.style.backgroundColor = '#fff';
                imgWrapper.style.borderRadius = '8px';
                imgWrapper.style.overflow = 'hidden';
                imgWrapper.style.position = 'relative';
                imgWrapper.style.cursor = 'pointer';
                imgWrapper.style.transition = 'transform 0.2s ease, box-shadow 0.2s ease';

                // 图片悬停效果
                imgWrapper.addEventListener('mouseenter', () => {
                    imgWrapper.style.transform = 'scale(1.02)';
                    imgWrapper.style.boxShadow = '0 4px 10px rgba(0, 0, 0, 0.2)';
                });
                imgWrapper.addEventListener('mouseleave', () => {
                    imgWrapper.style.transform = 'scale(1)';
                    imgWrapper.style.boxShadow = 'none';
                });

                const img = document.createElement('img');
                img.src = src;
                img.style.width = '100%';
                img.style.height = 'auto';
                img.style.borderRadius = '8px';
                img.alt = '图片';

                // 选中效果
                const overlay = document.createElement('div');
                overlay.style.position = 'absolute';
                overlay.style.top = '0';
                overlay.style.left = '0';
                overlay.style.width = '100%';
                overlay.style.height = '100%';
                overlay.style.backgroundColor = 'rgba(0, 123, 255, 0.5)';
                overlay.style.display = 'none';
                overlay.style.borderRadius = '8px';
                imgWrapper.appendChild(overlay);

                imgWrapper.appendChild(img);
                container.appendChild(imgWrapper);
                imageElements.push({ src, wrapper: imgWrapper, overlay });

                // 点击图片进行选中/取消
                imgWrapper.addEventListener('click', () => {
                    if (selectedImages.has(src)) {
                        selectedImages.delete(src);
                        overlay.style.display = 'none';
                    } else {
                        selectedImages.add(src);
                        overlay.style.display = 'block';
                    }
                });
            });

            // 全选按钮
            const selectAllButton = document.createElement('button');
            selectAllButton.textContent = '全选';
            selectAllButton.style.position = 'fixed';
            selectAllButton.style.bottom = '100px';
            selectAllButton.style.right = '20px';
            selectAllButton.style.zIndex = '10001';
            selectAllButton.style.padding = '10px 20px';
            selectAllButton.style.backgroundColor = '#007BFF';
            selectAllButton.style.color = '#fff';
            selectAllButton.style.border = 'none';
            selectAllButton.style.borderRadius = '8px';
            selectAllButton.style.cursor = 'pointer';
            selectAllButton.style.boxShadow = '0 4px 6px rgba(0, 0, 0, 0.1)';
            selectAllButton.style.fontSize = '14px';
            selectAllButton.style.fontWeight = '500';
            selectAllButton.style.transition = 'background-color 0.3s ease';
            container.appendChild(selectAllButton);

            // 全选按钮悬停效果
            selectAllButton.addEventListener('mouseenter', () => {
                selectAllButton.style.backgroundColor = '#0056b3';
            });
            selectAllButton.addEventListener('mouseleave', () => {
                selectAllButton.style.backgroundColor = '#007BFF';
            });

            selectAllButton.addEventListener('click', () => {
                imageElements.forEach(({ src, overlay }) => {
                    selectedImages.add(src);
                    overlay.style.display = 'block';
                });
            });

            // 取消全选按钮
            const deselectAllButton = document.createElement('button');
            deselectAllButton.textContent = '取消全选';
            deselectAllButton.style.position = 'fixed';
            deselectAllButton.style.bottom = '60px';
            deselectAllButton.style.right = '20px';
            deselectAllButton.style.zIndex = '10001';
            deselectAllButton.style.padding = '10px 20px';
            deselectAllButton.style.backgroundColor = '#FF5722';
            deselectAllButton.style.color = '#fff';
            deselectAllButton.style.border = 'none';
            deselectAllButton.style.borderRadius = '8px';
            deselectAllButton.style.cursor = 'pointer';
            deselectAllButton.style.boxShadow = '0 4px 6px rgba(0, 0, 0, 0.1)';
            deselectAllButton.style.fontSize = '14px';
            deselectAllButton.style.fontWeight = '500';
            deselectAllButton.style.transition = 'background-color 0.3s ease';
            container.appendChild(deselectAllButton);

            // 取消全选按钮悬停效果
            deselectAllButton.addEventListener('mouseenter', () => {
                deselectAllButton.style.backgroundColor = '#e64a19';
            });
            deselectAllButton.addEventListener('mouseleave', () => {
                deselectAllButton.style.backgroundColor = '#FF5722';
            });

            deselectAllButton.addEventListener('click', () => {
                imageElements.forEach(({ src, overlay }) => {
                    selectedImages.delete(src);
                    overlay.style.display = 'none';
                });
            });

            // 下载选中图片按钮
            const downloadSelectedButton = document.createElement('button');
            downloadSelectedButton.textContent = '下载选中图片(ZIP)';
            downloadSelectedButton.style.position = 'fixed';
            downloadSelectedButton.style.bottom = '20px';
            downloadSelectedButton.style.right = '20px';
            downloadSelectedButton.style.zIndex = '10001';
            downloadSelectedButton.style.padding = '10px 20px';
            downloadSelectedButton.style.backgroundColor = '#28A745';
            downloadSelectedButton.style.color = '#fff';
            downloadSelectedButton.style.border = 'none';
            downloadSelectedButton.style.borderRadius = '8px';
            downloadSelectedButton.style.cursor = 'pointer';
            downloadSelectedButton.style.boxShadow = '0 4px 6px rgba(0, 0, 0, 0.1)';
            downloadSelectedButton.style.fontSize = '14px';
            downloadSelectedButton.style.fontWeight = '500';
            downloadSelectedButton.style.transition = 'background-color 0.3s ease';
            container.appendChild(downloadSelectedButton);

            // 下载按钮悬停效果
            downloadSelectedButton.addEventListener('mouseenter', () => {
                downloadSelectedButton.style.backgroundColor = '#218838';
            });
            downloadSelectedButton.addEventListener('mouseleave', () => {
                downloadSelectedButton.style.backgroundColor = '#28A745';
            });

            downloadSelectedButton.addEventListener('click', async () => {
                if (selectedImages.size === 0) {
                    alert('请先选择图片!');
                    return;
                }

                const zip = new JSZip();
                const selectedArray = Array.from(selectedImages);

                for (let i = 0; i < selectedArray.length; i++) {
                    const src = selectedArray[i];
                    const filename = `image_${i + 1}.${src.split('.').pop().split('?')[0]}`;
                    const response = await fetch(src);
                    const blob = await response.blob();
                    zip.file(filename, blob);
                }

                const content = await zip.generateAsync({ type: 'blob' });
                const link = document.createElement('a');
                link.href = URL.createObjectURL(content);
                link.download = 'selected_images.zip';
                link.click();
            });
        });
    }
})();