Greasy Fork

Greasy Fork is available in English.

下载当前页面指定数据 (img, video, audio, ...)

调用 downloadDataInOrder(obtainDataNodes(document.querySelectorAll('数据节点'), 'file')) 方法,并传入数据节点,根据传入的数据节点,下载网页上的数据并保存到本地

当前为 2024-11-05 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         下载当前页面指定数据 (img, video, audio, ...)
// @namespace    http://tampermonkey.net/
// @version      1.0.2
// @description  调用 downloadDataInOrder(obtainDataNodes(document.querySelectorAll('数据节点'), 'file')) 方法,并传入数据节点,根据传入的数据节点,下载网页上的数据并保存到本地
// @author       slowFever
// @match        *://*/*
// @match        *
// @connect      *
// @grant        unsafeWindow
// @grant        GM_xmlhttpRequest
// @run-at       document-idle
// ==/UserScript==

(function() {
    'use strict';

    /**
     * @name 获取数据节点的函数
     * @param nodes 传入单个节点,或多个节点(img, video, audio, ...)
     * @returns Array[]
     */
    function obtainDataNodes(nodes) {
        let nodeDataList = [];
        nodes.forEach(node => {
            const src = node.getAttribute('src');
            if (src && !nodeDataList.includes(src)) {
                nodeDataList.push(src);
            }
        });
        console.log(`获取到${nodeDataList.length}条数据`)
        return nodeDataList;
    }

    /**
     * @name 下载数据的函数
     * @param url 下载地址
     * @param filename 文件名
     * @returns {Promise<void>}
     */
    function downloadFile(url, filename) {
        return new Promise((resolve, reject) => {
            GM_xmlhttpRequest({
                method: "GET",
                url: url,
                responseType: "blob", // 指定响应类型为 blob
                onload: function(response) {
                    if (response.status === 200) {
                        const blob = new Blob([response.response]); // 创建 Blob 对象
                        const link = document.createElement('a'); // 创建 <a> 标签
                        link.href = URL.createObjectURL(blob); // 创建 URL 对象
                        link.download = filename; // 设置下载的文件名
                        document.body.appendChild(link); // 添加到文档中
                        link.click(); // 模拟点击下载
                        document.body.removeChild(link); // 下载完成后移除 <a> 标签
                        console.log(`成功下载数据:${filename}`);
                        resolve(); // 下载完成,调用 resolve
                    } else {
                        console.error('下载失败,状态码:', response.status);
                        reject(`下载失败,状态码: ${response.status}`);
                    }
                },
                onerror: function(error) {
                    console.error('下载出错:', error);
                    reject(error); // 出错时调用 reject
                }
            });
        });
    }

    /**
     * @name 按顺序下载数据的函数
     * @param nodesData 数据节点
     * @param prefix 文件名前缀
     */
    async function downloadDataInOrder(nodesData, prefix = 'file') {
        for (let i = 0; i < nodesData.length; i++) {
            const url = nodesData[i];
            const fileName = `${prefix}-${i + 1}.${url.split('.').pop().split('?')[0]}`;
            try {
                await downloadFile(url, fileName); // 等待下载完成后再进行下一个
            } catch (error) {
                console.error(`文件 ${fileName} 下载失败:`, error);
            }
        }
    }

    // 将函数暴露到全局,以便在控制台调用
    unsafeWindow.downloadDataInOrder = downloadDataInOrder;
    unsafeWindow.obtainDataNodes = obtainDataNodes;

    // 提示用户可以通过控制台调用函数
    (async () => {
        console.log("下载指定数据脚本加载完成,当前版本:", GM_info.script.version);
        await new Promise(resolve => setTimeout(resolve, 1000)); // 延时1秒
        console.log("%c使用脚本方法:↓ ↓ ↓", "color:#ec2c64");
        await new Promise(resolve => setTimeout(resolve, 1000)); // 再延时1秒
        console.log("%cdownloadDataInOrder(obtainDataNodes(document.querySelectorAll('数据节点'), 'file'))",  "color:#0f59a4; background:#eef7f2; font-size:1.5rem; padding:0.15rem 0.35rem; margin: 1rem auto; font-family: Rockwell; border: 2px solid #0f59a4; border-radius: 4px;font-weight: bold; text-shadow: 1px 1px 1px #0f59a4;");
    })();
})();