Greasy Fork

Greasy Fork is available in English.

森空岛图片下载器

给文章详情页添加一个批量下载附件图片的按钮

目前为 2024-09-05 提交的版本,查看 最新版本

// ==UserScript==
// @name         森空岛图片下载器
// @description  给文章详情页添加一个批量下载附件图片的按钮
// @author       小旦
// @version      1.0.3
// @match        *://*.skland.com/article?id=*
// @grant        GM_download
// @run-at       document-end
// @require      https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js
// @supportURL   http://greasyfork.icu/zh-CN/scripts/506756-%E6%A3%AE%E7%A9%BA%E5%B2%9B%E5%9B%BE%E7%89%87%E4%B8%8B%E8%BD%BD%E5%99%A8/feedback
// @license      MIT
// @namespace http://greasyfork.icu/zh-CN/users/1002415-%E5%B0%8F%E6%97%A6
// ==/UserScript==

(function() {
    'use strict';

    const createDownloadButton = () => {
        const downloadButton = document.createElement('button');
        downloadButton.textContent = '下载原图';
        downloadButton.style.position = 'relative';
        downloadButton.style.padding = '9px';
        downloadButton.style.display = 'inline-block';
        downloadButton.style.backgroundColor = 'rgb(55, 55, 55)';
        downloadButton.style.border = '5px solid rgb(200, 235, 33)';
        downloadButton.style.borderRadius = '37px';
        downloadButton.style.marginTop = '-2px';
        downloadButton.style.color = 'rgb(255, 255, 255)';
        downloadButton.style.fontSize = '12px';
        downloadButton.style.lineHeight = '16px';
        downloadButton.style.fontWeight = '700';
        downloadButton.style.fontFamily = 'akrobat, Arial, sans-serif';
        downloadButton.style.cursor = 'pointer';

        downloadButton.addEventListener('click', function() {
            downloadImages();
        });

        return downloadButton;
    };

    const addTargetButton = (targetDiv) => {
        if (!targetDiv) return;
        const button = createDownloadButton();
        targetDiv.appendChild(button);
    };

    const getTargetElement = () => {
        const relationGroupClassNamePattern = /RelationGroup__Wrapper-sc-\w+-\d+/;
        const elements = document.querySelectorAll('*');
        for (let element of elements) {
            if (element.classList && element.classList.value.match(relationGroupClassNamePattern)) {
                return element;
            }
        }
        return null;
    };

    function downloadImages() {
        const containers = document.querySelectorAll('.swiper-item');

        if (!containers.length) {
            const excludeUrls = [
                'https://bbs.hycdn.cn/image/2024/02/01/d2d131efc9910cf68885aab0294ec221.gif',
                'https://bbs.hycdn.cn/image/2024/01/18/1bcc08672a86a2be342c0f0c48c5492c.gif'
            ];

            const allImgs = document.querySelectorAll(
                'img.sc-fHslGR.flPNXF[src^="https://bbs.hycdn.cn/image/"][src$=".webp"], ' +
                'img.sc-fHslGR.flPNXF[src^="https://bbs.hycdn.cn/image/"][src$=".gif"]'
            );

            const imgs = Array.from(allImgs).filter(img => {
                if (excludeUrls.includes(img.src)) return false;

                const styleAttr = img.getAttribute('style');
                if (styleAttr === 'object-fit: cover; object-position: center center;') return false;

                return true;
            });

            if (!imgs.length) {
                console.error('未找到包含指定来源的 webp 或 gif 图片,或所有找到的图片都被排除');
                return;
            }

            const now = new Date();
            const timestamp = now.toISOString().slice(0, 19).replace(/[-:T]/g, '');
            let count = 1;

            imgs.forEach(img => {
                handleImageDownload(img, timestamp, count++);
            });
        } else {
            const now = new Date();
            const timestamp = now.toISOString().slice(0, 19).replace(/[-:T]/g, '');
            let count = 1;

            containers.forEach((container, index) => {
                if (index === 0) {
                    const firstImage = container.querySelector('img');
                    if (firstImage) {
                        const images = Array.from(container.querySelectorAll('img')).slice(1);
                        images.forEach(img => {
                            handleImageDownload(img, timestamp, count++);
                        });
                    } else {
                        console.error('未找到首张图片');
                    }
                } else {
                    container.querySelectorAll('img').forEach(img => {
                        handleImageDownload(img, timestamp, count++);
                    });
                }
            });
        }
    }

    function handleImageDownload(img, timestamp, count) {
        const src = img.src;
        const filename = `${timestamp}_${count}.webp`;
        console.log(`Downloading image: ${filename}`);
        GM_download({
            url: src,
            name: filename,
            onload: function(response) {
                console.log(`Downloaded: ${filename}`);
            },
            onerror: function(error) {
                console.error(`Failed to download: ${filename}, error: ${error}`);
            }
        });
    }

    const delayedExecution = () => {
        const targetDiv = getTargetElement();
        if (targetDiv) {
            addTargetButton(targetDiv);
        } else {
            console.log("未找到目标 div");
        }
    };

    setTimeout(delayedExecution, 3000);
})();