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

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

目前為 2024-11-05 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

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

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         下载当前页面指定数据 (img, video, audio, ...)
// @namespace    http://tampermonkey.net/
// @version      1.0.4
// @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> 标签
                        const objectURL = URL.createObjectURL(blob); // 创建 Blob URL
                        link.href = objectURL;
                        link.download = filename; // 设置下载的文件名
                        document.body.appendChild(link); // 添加到文档中
                        link.click(); // 模拟点击下载
                        document.body.removeChild(link); // 下载完成后移除 <a> 标签
                        URL.revokeObjectURL(objectURL); // 释放 Blob URL
                        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 文件名前缀
     * @param batchSize 每次下载的最大文件数量
     */
    async function downloadDataInOrder(nodesData, prefix = 'file', batchSize = 10) {
        for (let i = 0; i < nodesData.length; i += batchSize) {
            const batch = nodesData.slice(i, i + batchSize); // 获取当前批次的数据
            await Promise.all(batch.map((url, index) => {
                const fileName = `${prefix}-${i + index + 1}.${url.split('.').pop().split('?')[0]}`;
                return downloadFile(url, fileName);
            }));
            console.log(`完成批次 ${Math.floor(i / batchSize) + 1} 的下载`);
        }
    }

    // 将函数暴露到全局,以便在控制台调用
    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;");
    })();
})();