图片下载器

批量下载图片,一个可扩展的图片下载器。

目前為 2022-02-11 提交的版本,檢視 最新版本

// ==UserScript==
// @name         图片下载器
// @namespace    http://tampermonkey.net/
// @version      3.2.3
// @description  批量下载图片,一个可扩展的图片下载器。
// @author       Gscsd
// @include        *
// @icon         data:image/jpeg;base64,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
// @grant        GM_xmlhttpRequest
// @grant        GM_download
// @grant        GM_setValue
// @grant        GM_log
// @grant        GM_notification
// @connect      *
// @require      https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js
// @require      https://cdn.bootcdn.net/ajax/libs/jszip/3.7.1/jszip.js
// @run-at       document-end
// @noframes
// ==/UserScript==
(function () {
    'use strict';

    function depthTest(fa, a) {
        var sum = 0;
        while (1) {
            if (a === fa) break;
            a = $(a).parent()[0];
            sum++;

        }
        return sum
    }

    function FindBrothers(a) {
        let par = $(a).parent()[0], sea = $(par).find('img').toArray();
        if (sea.length === 1) return FindBrothers(par)
        else {
            let depth = depthTest(par, getimg), sea1 = [];
            sea.forEach((item) => {
                if (depthTest(par, item) === depth) sea1.push(item)
            })
            sea = sea1;
            if (sea.length === 1) return FindBrothers(par);
            return sea
        }
    }

    //重写下载函数
    /*function GM_download(url, name) {
        let a = document.createElement('a')
        a.download = name
        a.href = url
        a.style.display = 'none'
        document.body.appendChild(a)
        a.click()
        a.remove()
    }*/

    class TaskQueue {
        downloadIndex = 0;
        retryIndex = 0;
        results = [];
        transfer = [];
        error = [];
        //0未下载 1下载排队中 2下载排队完成,等待中 3下载成功 4下载失败 5下载完成
        downloadStatus = 0

        constructor(o) {
            if ($('#v_bar').length) {
                GM_notification({text: '下载中,请稍等...', timeout: 3000})
                return
            }
            /*
            api:
                TaskQueue(details)
                图片下载类。
                Property of details:
                    imglist: 图片下载链接列表,默认[],必选;
                    thread: 启用下载线程,默认10;
                    retryNum: 下载出错,重试次数,默认5;
                    filename: 打包zip文件名,默认当前网站标题(稍做处理);
                    timeout: 单张图片请求超时,默认60 * 1000ms,即1min;
                    autoRetry: 下载出错自动重试,默认false;
                    autoDownload: 重试失败后自动下载,默认false;
                    onload: 成功回调,默认null;
                    onerror: 失败回调,默认null。
                e.g.
                    let imglist = document.querySelectorAll('.normal-img'), Imglist = []
                    let len = imglist.length;
                    for (let i = 0; i < len; i++) {
                        Imglist.push(new URL(imglist[i].getAttribute('data-src').split('@')[0], location.href).href)
                    }
                    setTimeout(_ => {
                        if (len >= 2) {
                            if (confirm(`下载全部${len}张图片?`)) {
                                new TaskQueue({
                                    imglist: Imglist,
                                    filename: document.title.split('-')[0].trim()
                                });
                            }
                        }
                    }, 2000)

            more:
                1.启用本下载器后,超链接跳转在下载未完成或手动取消前将被禁止,请务必在不需要时关闭本下载器;
                2.仅支持zip批量打包下载,兼容移动端kiwi浏览器;
                3.请允许跨域图片下载权限;
                4.若蓝色下载进度条,超过默认超时时间仍卡死,请刷新重试;
                5.由于现在不少网站使用了lazyload技术,不一定能获取到图片链接,所以最好从头划到尾,等图片加载后再下载;
                6.若普通点击,无法捕获到图片,启动下载,可按照上api自行适配;
                7.学艺不精,水平有限,内行勿笑。

            */
            ({
                imglist: this.queue = [],
                thread: this.thread = 10,
                retryNum: this.retryNum = 5,
                filename: this.filename = document.title.replace(/- .*?$/, '').trim(),
                //请求超时
                timeout: this.timeout = 60 * 1000,
                //自动重试
                autoRetry: this.autoRetry = false,
                //重试失败后自动下载
                autoDownload: this.autoDownload = false,
                //成功回调
                onload: this.onload = null,
                //失败回调
                onerror: this.onerror = null
            } = o);
            this.progressList = Array(this.queue.length)
            $('body').append(`<div id="v_bar"><div></div></div>`)
            $('head').append(`<style>
            #v_bar{
                width: 1%;
                height: 80%;
                background-color: #00ffff;
                position: fixed;
                top: 50%;
                left: 0;
                z-index: 999999999;
                transform: translate(0,-50%);
            }
            #v_bar>div{
                height: 100%;
                background-color: #8c939d;
            }
            </style>`)
            GM_notification({text: '开始下载', title: this.filename, timeout: 3000})
            this.downloadStart()
        }

        // 下载开始
        downloadStart() {
            this.downloadStatus = 1;
            let download = () => {
                let index = this.downloadIndex
                if (!this.transfer[index] || ($.inArray(index, this.error) > -1 && this.error.shift() + 1)) {
                    this.downloadIndex < this.queue.length - 1 && this.downloadIndex++
                    this.transfer[index] = Promise.race([new Promise((resolve, reject) => {
                        GM_xmlhttpRequest({
                            method: "GET",
                            url: this.queue[index],
                            responseType: "blob",
                            timeout: this.timeout,
                            onload: r => {
                                if (r.readyState === 4 && r.status === 200) {
                                    resolve(r.response)
                                } else {
                                    reject(new Blob([], {type: "image/jpeg"}))
                                }
                                this.judgeFinish(download)
                            },
                            onprogress: xhr => {
                                if (xhr.lengthComputable) {
                                    this.progressList[index] = xhr.loaded / xhr.total * 100;
                                    this.progressBar()
                                }
                            },
                            onerror: _ => {
                                reject(new Blob([], {type: "image/jpeg"}))
                                this.judgeFinish(download)
                            }
                        });
                    }), new Promise((_, reject) => {
                        setTimeout(reject, this.timeout, new Blob([], {type: "image/jpeg"}))
                    })])
                } else {
                    //快速跳过
                    this.downloadIndex < this.queue.length - 1 && this.downloadIndex++ && download()
                }
            }
            // 建立多少个线程
            let thread = [this.thread, this.queue.length];
            //重试则按出错数开启线程
            this.error.length > 0 ? thread.push(this.error.length) : null
            for (let i = 0; i < Math.min(...thread); i++) {
                download(i)
            }
        }

        //判断队列是否完成,并进行后续处理
        judgeFinish(callback) {
            //当下载列表已遍历完成,检验是否每段都下载成功
            if (this.queue.length === this.transfer.length && this.error.length === 0) {
                if (this.downloadStatus !== 1) return
                this.downloadStatus = 2;
                //下载状态改变
                Promise.allSettled(this.transfer).then(all => {
                    all.forEach((item, index) => {
                        if (item.status === "rejected") {
                            this.progressList[index] = 0
                            this.error.push(index)
                        }
                    })
                    //下载出错,尝试重新下载
                    if (this.error.length > 0) {
                        let choice = !this.retryIndex && !this.autoRetry && confirm(`${this.error.length}张图片下载出错。强行打包下载?尝试重新下载?`)
                        if (choice) {
                            this.downloadStatus = 3;
                            this.results = all.map(one => one.value || one.reason);
                            this.Zip()
                            return
                        }
                        if (this.retryIndex === this.retryNum) {
                            GM_notification({text: '下载失败', title: this.filename, timeout: 3000})
                            GM_log('下载失败')
                            let choice1 = this.autoDownload || confirm(`重试5次下载失败。强行打包下载?放弃下载?`)
                            if (choice1) {
                                this.downloadStatus = 3;
                                this.results = all.map(one => one.value || one.reason);
                                this.Zip()
                            } else {
                                this.downloadStatus = 4
                                $('#v_bar').remove()
                                this.onerror && this.onerror()
                            }

                        } else !choice && this.retryAll()
                    }
                    //下载成功
                    else {
                        this.downloadStatus = 3;
                        this.results = all.map(one => one.value);
                        this.Zip()
                    }
                })

            } else callback && callback()

        }

        retryAll() {
            this.downloadIndex = 0;
            this.retryIndex++
            this.downloadStart()
        }

        //进度条
        progressBar() {
            let all = 0
            this.progressList.forEach(item => {
                all += item || 0
            })
            $('#v_bar>div').height((100 - all / this.progressList.length).toFixed(2) + '%')
            return 1
        }


        //处理非法文件名称
        legalize(str) {
            var pattern = new RegExp("[\\\\:<>/?*|]");
            var rs = "";
            for (var i = 0; i < str.length; i++) {
                rs += str.substr(i, 1).replace(pattern, '');
            }
            return rs.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, "");
            //const invalidchar = `~!@#$%^&*,。;‘’\\{【】[]}|`;
        }

        //打包下载
        Zip() {
            var zip = new JSZip(), num = this.queue.length.toString().length;
            // var allen = this.queue.length, num = allen > 99 ? 3 : (allen > 9 ? 2 : 1);
            this.results.forEach((content, index) => {
                // 重置进度条状态
                !index && this.progressList.fill(0) && this.progressBar() && $('#v_bar').css("background-color", "red")
                let name = `${(index + 1).toString().padStart(num, '0')}.${content.type.split('/')[1].replace('jpeg', 'jpg')}`
                zip.file(name, content, {blob: true});
                zip.file(name).async("blob", metadata => {
                    this.progressList[index] = metadata.percent;
                    this.progressBar()

                })
            })
            zip.generateAsync({type: "blob"})
                .then(content => {
                    let blob_url = URL.createObjectURL(content)
                    // 重置进度条状态
                    this.progressList.fill(0) && this.progressBar() && $('#v_bar').css("background-color", "#e0e052")
                    GM_download({
                        url: blob_url,
                        name: this.legalize(this.filename) + '.zip',
                        onload: _ => {
                            $('#v_bar').remove()
                            GM_notification({text: '下载成功', title: this.filename, timeout: 3000})
                            GM_log('下载成功')
                            this.downloadStatus = 5;
                            URL.revokeObjectURL(blob_url)
                            document.querySelectorAll("a").forEach(a => a.removeEventListener("click", prevent));
                            this.onload && this.onload()
                        },
                        onprogress: r => {
                            if (r.lengthComputable) {
                                this.progressList.fill(r.loaded / r.total * 100);
                                this.progressBar()
                            }
                        },
                        onerror: _ => {
                            $('#v_bar').remove()
                            GM_notification({text: '下载至本地失败', title: this.filename, timeout: 3000})
                            GM_log('下载至本地失败')
                            this.downloadStatus = 5;
                            URL.revokeObjectURL(blob_url)
                            document.querySelectorAll("a").forEach(a => a.removeEventListener("click", prevent));
                            this.onerror && this.onerror()
                        }
                    });
                    // GM_download(blob_url, this.legalize(this.filename) + '.zip');
                    // $('#v_bar').remove()
                    // GM_notification({text: '下载成功', title: this.filename, timeout: 3000})
                    // GM_log('下载成功')
                    // this.downloadStatus = 5;
                    // URL.revokeObjectURL(blob_url)
                    // this.onsuccess && this.onsuccess()
                });
        }
    }

    unsafeWindow.TaskQueue = TaskQueue;

    //1.阻止a标签跳转
    function prevent(e) {
        e.preventDefault()
    }

    document.querySelectorAll("a").forEach(a => a.addEventListener("click", prevent));
    //2.移除onclick属性
    $("[onclick]").removeAttr("onclick");
    document.querySelectorAll("img").forEach(img => {
        let a_el = $(img).parents('a'), click_el = a_el.length ? a_el[0] : img
        $(click_el).click(e => {
            e.stopImmediatePropagation()
            if ($('#v_bar').length) {
                GM_notification({text: '下载中,请稍等...', timeout: 3000})
                return
            }
            window.getimg = e.target;
            let imglist, width = [], height = [];
            imglist = FindBrothers(e.target).map((one, index) => {
                [width[index], height[index]] = [one.naturalWidth, one.naturalHeight]
                return one.src
            });
            let len = imglist.length;
            if (len === 0) return;
            if (confirm(`下载全部${len}张图片?`)) {
                new TaskQueue({imglist: imglist})
            } else document.querySelectorAll("a").forEach(a => a.removeEventListener("click", prevent));

        });
    })

})();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址