Greasy Fork

Greasy Fork is available in English.

批量图片提取与下载

提取图片后支持全选、取消全选、一键下载全部图片和下载选中图片为 ZIP 文件。

当前为 2024-12-25 提交的版本,查看 最新版本

// ==UserScript==
// @name         批量图片提取与下载
// @namespace    http://tampermonkey.net/
// @version      1.4.0
// @description  提取图片后支持全选、取消全选、一键下载全部图片和下载选中图片为 ZIP 文件。
// @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 = '5px';
    startButton.style.cursor = 'pointer';
    startButton.style.boxShadow = '0 2px 4px rgba(0, 0, 0, 0.2)';
    startButton.style.fontSize = '16px';
    document.body.appendChild(startButton);

    // 点击“开始”按钮
    startButton.addEventListener('click', () => {
        const input = prompt('请输入链接(每行一个):');
        if (!input) return;

        const links = input.split('\n').map(link => link.trim()).filter(link => link);

        if (links.length === 0) {
            alert('请输入至少一个有效链接');
            return;
        }

        // 创建图片展示容器
        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.9)';
        container.style.overflowY = 'scroll';
        container.style.zIndex = '10000';
        container.style.display = 'flex';
        container.style.flexWrap = 'wrap';
        container.style.gap = '10px';
        container.style.padding = '20px';
        document.body.appendChild(container);

        // 创建关闭按钮
        const closeButton = document.createElement('button');
        closeButton.textContent = '关闭';
        closeButton.style.position = 'fixed';
        closeButton.style.top = '10px';
        closeButton.style.right = '10px';
        closeButton.style.zIndex = '10001';
        closeButton.style.padding = '10px 20px';
        closeButton.style.backgroundColor = '#FF4C4C';
        closeButton.style.color = '#fff';
        closeButton.style.border = 'none';
        closeButton.style.borderRadius = '5px';
        closeButton.style.cursor = 'pointer';
        container.appendChild(closeButton);

        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% - 10px)';
                imgWrapper.style.display = 'flex';
                imgWrapper.style.alignItems = 'center';
                imgWrapper.style.justifyContent = 'center';
                imgWrapper.style.backgroundColor = '#fff';
                imgWrapper.style.borderRadius = '5px';
                imgWrapper.style.overflow = 'hidden';
                imgWrapper.style.position = 'relative';
                imgWrapper.style.cursor = 'pointer';

                const img = document.createElement('img');
                img.src = src;
                img.style.width = '100%';
                img.style.height = 'auto';
                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, 255, 0, 0.5)';
                overlay.style.display = 'none';
                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 = '70px';
            selectAllButton.style.right = '10px';
            selectAllButton.style.zIndex = '10001';
            selectAllButton.style.padding = '10px 20px';
            selectAllButton.style.backgroundColor = '#007BFF';
            selectAllButton.style.color = '#fff';
            selectAllButton.style.border = 'none';
            selectAllButton.style.borderRadius = '5px';
            selectAllButton.style.cursor = 'pointer';
            container.appendChild(selectAllButton);

            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 = '40px';
            deselectAllButton.style.right = '10px';
            deselectAllButton.style.zIndex = '10001';
            deselectAllButton.style.padding = '10px 20px';
            deselectAllButton.style.backgroundColor = '#FF5722';
            deselectAllButton.style.color = '#fff';
            deselectAllButton.style.border = 'none';
            deselectAllButton.style.borderRadius = '5px';
            deselectAllButton.style.cursor = 'pointer';
            container.appendChild(deselectAllButton);

            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 = '10px';
            downloadSelectedButton.style.right = '10px';
            downloadSelectedButton.style.zIndex = '10001';
            downloadSelectedButton.style.padding = '10px 20px';
            downloadSelectedButton.style.backgroundColor = '#28A745';
            downloadSelectedButton.style.color = '#fff';
            downloadSelectedButton.style.border = 'none';
            downloadSelectedButton.style.borderRadius = '5px';
            downloadSelectedButton.style.cursor = 'pointer';
            container.appendChild(downloadSelectedButton);

            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();
            });
        });
    });
})();