Greasy Fork

Greasy Fork is available in English.

花瓣网下载

花瓣网(huaban.com)用户画板图片批量下载到本地

当前为 2018-05-25 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         花瓣网下载
// @namespace    https://www.saintic.com/
// @version      0.1
// @description  花瓣网(huaban.com)用户画板图片批量下载到本地
// @author       staugur
// @match        http*://huaban.com/boards/*
// @require      https://cdn.bootcss.com/FileSaver.js/2014-11-29/FileSaver.min.js
// @grant        GM_setClipboard
// @license      MIT
// @date         2018-05-25
// @modified     none
// @github       https://github.com/staugur/grab_huaban_board
// @supportURL   https://github.com/staugur/grab_huaban_board/issues
// ==/UserScript==

(function() {
    'use strict';
    /*
        公共接口
    */
    //字符串是否包含子串
    function isContains(str, substr) {
        //str是否包含substr
        return str.indexOf(substr) >= 0;
    }
    //下载保存图片
    function saveImage(imgUrl, imgName) {
        //imgUrl: 图片地址; imgName: 保存的文件名
        try {
            const xhr = new XMLHttpRequest();
            xhr.open('GET', imgUrl, true);
            xhr.responseType = 'blob';
            xhr.onload = () => {
                if (xhr.status === 200) {
                    //将图片文件用浏览器中下载
                    saveAs(xhr.response, imgName);
                }
            };
            xhr.send();
        } catch (e) {
            console.log(e);
        }
    }
    //加载css文件
    function addCSS(href) {
        var link = document.createElement('link');
        link.type = 'text/css';
        link.rel = 'stylesheet';
        link.href = href;
        document.getElementsByTagName("head")[0].appendChild(link);
    }
    //加载js文件
    function addJS(src, cb) {
        var script = document.createElement("script");
        script.type = "text/javascript";
        script.src = src;
        document.getElementsByTagName('head')[0].appendChild(script);
        script.onload = typeof cb === "function" ? cb : function() {};
    }
    //由于@require方式引入jquery时layer使用异常,故引用cdn中jquery v1.10.1;加载完成后引用又拍云中layer v3.1.1
    addJS("https://cdn.bootcss.com/jquery/1.10.1/jquery.min.js", function() {
        addJS("https://static.saintic.com/cdn/layer/3.1.1/layer.js");
    });
    var board_id = window.location.pathname.split('/')[1] === "boards" ? window.location.pathname.split('/')[2] : "";
    var protocol = window.location.protocol;
    /*
        下载图片
    */
    //交互确定下载方式
    function interactive(pins) {
        var msg = [
            '<b>当前画板共抓取' + pins.length + '张图片!</b><small>提示: 只有登录后才可以抓取几乎所有图片哦。</small><br/>',
            '<b>请选择以下三种下载方式:</b><br/>',
            '1. <i>文本</i>: <br/>&nbsp;&nbsp;&nbsp;&nbsp;即所有图片地址按行显示,提供复制,粘贴至迅雷、QQ旋风等下载工具批量下载即可,推荐使用此方法。<br/>',
            '2. <i>本地</i>: <br/>&nbsp;&nbsp;&nbsp;&nbsp;即所有图片直接保存到硬盘中,由于是批量下载,所以浏览器设置中请关闭"下载前询问每个文件的保存位置",并且允许浏览器下载多个文件的授权申请,以保证可以自动批量保存,否则每次保存时会弹出询问,对您造成困扰。<br/>',
            '3. <i>远程</i>: <br/>&nbsp;&nbsp;&nbsp;&nbsp;即所有图片将由第三方服务器下载并压缩,提供压缩文件链接,直接下载此链接解压即可。<br/>',
            '<br/><p><b>寻求帮助?</b><a href="https://www.saintic.com/blog/256.html" target="_blank" title="帮助文档" style="color: green;">请点击我!</a></p>'
        ].join('');
        layer.confirm(msg, {
            title: "选择画板图片下载方式",
            closeBtn: false,
            shadeClose: false,
            shade: 0,
            btn: ['文本', '本地', '远程'],
            btnAlign: 'c',
            btn3: function(index, layero) {
                downloadPicRemotely(pins);
            }
        }, function(index, layero) {
            downloadPicText(pins);
        }, function(index) {
            downloadPicLocally(pins);
        });
    }
    //本地下载
    function downloadPicLocally(pins) {
        for (var i = 0, len = pins.length; i < len; i++) {
            saveImage(pins[i].imgUrl, pins[i].imgName);
        }
    }
    //远端下载
    function downloadPicRemotely(pins) {
        $.ajax({
            url: "https://www.saintic.com/CrawlHuaban/",
            type: "POST",
            data: {
                board_id: board_id,
                pins: JSON.stringify(pins)
            },
            success: function(res) {
                if (res.success === true) {
                    var msg = "<b>下载任务已经提交!</b><br>根据画板图片数量,所需时间不等,请稍等数分钟后访问下载链接:<br><i><a href='" + res.downloadUrl + "' target='_blank'>" + res.downloadUrl + "</a></i><br>它将于" + res.expireTime + "过期,资源会被删除,请在那之前下载。";
                    layer.alert(msg, {
                        icon: 1,
                        title: "温馨提示",
                        btn: '我已知晓并复制下载链接',
                        btnAlign: 'c'
                    }, function(index) {
                        layer.close(index);
                        GM_setClipboard(res.downloadUrl);
                        layer.msg("复制成功", {
                            icon: 1
                        });
                    });
                } else {
                    layer.msg("第三方服务异常: " + res.msg);
                }
            }
        });
    }
    //文本方式下载,比如迅雷、QQ旋风
    function downloadPicText(pins) {
        var tip = '<b>请点击复制按钮,粘贴到迅雷等下载!</b><br/>',
            str = '';
        for (var i = 0, len = pins.length; i < len; i++) {
            str += pins[i].imgUrl + "\n";
        }
        layer.alert(tip + str, {
            title: "文本方式下载",
            btn: '复制',
            btnAlign: 'c',
            icon: 1,
            yes: function(index, layero) {
                layer.close(index);
                GM_setClipboard(str);
                layer.msg("复制成功", {
                    icon: 1
                });
            }
        });
    }
    //定位
    var d = document.getElementById('page').getElementsByClassName('action-buttons')[0];
    //插入下载画板按钮
    if (isContains(d.innerText, "下载此画板") === false) {
        d.insertAdjacentHTML('afterbegin', '<a href="#" id="downloadBoard" class="btn rbtn"><span class="text"> 下载此画板</span></a>');
    }
    //监听点击下载事件
    document.getElementById("downloadBoard").onclick = function() {
        if (board_id) {
            var retry = 100,
                limit = 100,
                board_url = protocol + '//huaban.com/boards/' + board_id;
            //get first pin data
            $.ajax({
                url: board_url,
                type: "GET",
                async: false,
                success: function(res) {
                    try {
                        //console.log(res);
                        if (res.hasOwnProperty("board") === true) {
                            var board_data = res.board,
                                pin_number = board_data.pin_count,
                                board_pins = board_data.pins;
                            //console.log("Current board <" + board_id + "> pins number is " + pin_number + ", first pins number is " + board_pins.length);
                            if (board_pins.length < pin_number) {
                                var last_pin = board_pins[board_pins.length - 1].pin_id;
                                while (1 <= retry) {
                                    //get ajax pin data
                                    var board_next_url = protocol + "//huaban.com/boards/" + board_id + "/?max=" + last_pin + "&limit=" + limit + "&wfl=1";
                                    $.ajax({
                                        url: board_next_url,
                                        type: "GET",
                                        async: false,
                                        success: function(res) {
                                            //console.log(res);
                                            var board_next_data = res.board;
                                            board_pins = board_pins.concat(board_next_data.pins);
                                            console.log("ajax load board with pin_id " + last_pin + ", get pins number is " + board_next_data.pins.length + ", merged");
                                            if (board_next_data.pins.length === 0) {
                                                retry = 0;
                                                return false;
                                            }
                                            last_pin = board_next_data.pins[board_next_data.pins.length - 1].pin_id;
                                        }
                                    });
                                    retry -= 1;
                                }
                            }
                            //console.log("共抓取" + board_pins.length + "个pin");
                            var pins = [];
                            for (var i = 0, len = board_pins.length; i < len; i++) {
                                var pin = board_pins[i];
                                pins.push({
                                    imgUrl: "http://img.hb.aicdn.com/" + pin.file.key + "_fw658",
                                    imgName: pin.pin_id + "." + pin.file.type.split("/")[1]
                                });
                            }
                            //交互确定下载方式
                            interactive(pins);
                        }
                    } catch (e) {
                        console.log(e);
                    }
                }
            });
        }
    };
})();