Greasy Fork

Greasy Fork is available in English.

Facebook Photos Bulk Downloader (Background Support)

Bulk download Facebook album photos in full resolution, supports background downloading with minimized interruption and optimized user experience.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Facebook Photos Bulk Downloader (Background Support)
// @namespace    麦克
// @version      2.1.4
// @description  Bulk download Facebook album photos in full resolution, supports background downloading with minimized interruption and optimized user experience.
// @author       麦克
// @match        https://www.facebook.com/*/photos/*
// @match        https://www.facebook.com/photo.php?*
// @match        https://www.facebook.com/photo?*
// @match        https://www.facebook.com/photo/*
// @grant        GM_download
// @grant        GM_notification
// @license      GPL-3.0-or-later
// ==/UserScript==

let iter = 0;
let MAXITER = 10;
let isDownloading = false;
let stopDownload = false;

// 创建 Fetch 按钮并确保其持久存在
(function () {
    const observer = new MutationObserver(() => {
        if (document.body && !document.querySelector('#fetch-button')) {
            let fetchBtn = document.createElement("div");
            fetchBtn.id = "fetch-button";
            fetchBtn.textContent = "⇩ Fetch Photos";
            fetchBtn.style.cssText = 'position:fixed;top:10px;right:10px;z-index:9999;padding:8px;background-color:#4caf50;color:white;border-radius:5px;cursor:pointer;';
            fetchBtn.onclick = startBatchDownload;
            document.body.appendChild(fetchBtn);
        }
    });
    observer.observe(document.body, { childList: true, subtree: true });
})();

// 仅在下载时防止页面关闭的提示
function handleBeforeUnload(event) {
    if (isDownloading && !stopDownload) {
        event.preventDefault();
        event.returnValue = '正在下载照片,您确定要离开吗?';
        return '正在下载照片,您确定要离开吗?';
    }
}

// 获取当前图片 URL
function getImageUrl() {
    const imgElement = document.querySelector('img[src*="scontent"]');
    return imgElement ? imgElement.src : null;
}

// 点击“下一张”按钮
function clickNextImage() {
    const nextBtn = document.querySelector('div[aria-label="下一张"], div[aria-label="Next"]');
    if (nextBtn) {
        nextBtn.click();
        return true;
    } else {
        const complexNextBtn = document.querySelector('div[role="button"][tabindex="0"] div[style*="background-image"]');
        if (complexNextBtn) {
            complexNextBtn.click();
            return true;
        }
    }
    return false;
}

// 下载图片并确保完成后翻页
function downloadImage(imgUrl, callback) {
    if (imgUrl) {
        const filename = imgUrl.split('?')[0].split('/').pop();
        console.log(`Downloading: ${filename}`);
        GM_download({
            url: imgUrl,
            name: filename,
            saveAs: false,
            onload: callback,
            onerror: callback,
        });
    } else {
        console.error('Failed to fetch image URL.');
        callback();
    }
}

// 批量下载函数
function batchDownload() {
    if (iter >= MAXITER || stopDownload) {
        endDownload();
        return;
    }

    const imgUrl = getImageUrl();
    if (imgUrl) {
        downloadImage(imgUrl, () => {
            iter++;
            if (clickNextImage()) {
                console.log(`Moving to image ${iter + 1}`);
                setTimeout(batchDownload, 1000); // 等待 1 秒后继续下载
            } else {
                endDownload();
            }
        });
    } else {
        console.error('Retry fetching image...');
        setTimeout(() => {
            if (!stopDownload) batchDownload();
        }, 1000);
    }
}

// 结束下载并移除事件监听器
function endDownload() {
    console.log('Download completed or stopped.');
    isDownloading = false;
    stopDownload = true;
    iter = 0;
    toggleBeforeUnload(false); // 移除 beforeunload 事件
    GM_notification({
        text: `Download ${stopDownload ? 'stopped' : 'completed'}: ${iter} photos`,
        title: 'Facebook Bulk Downloader',
        timeout: 5000
    });
}

// 启用或禁用 `beforeunload` 事件
function toggleBeforeUnload(enable) {
    if (enable) {
        window.addEventListener('beforeunload', handleBeforeUnload);
    } else {
        window.removeEventListener('beforeunload', handleBeforeUnload);
    }
}

// 开始批量下载
function startBatchDownload() {
    if (isDownloading) {
        console.warn('Download already in progress.');
        return;
    }
    iter = 0;
    stopDownload = false;
    MAXITER = parseInt(prompt("Enter the number of photos to download:", "10")) || 10;
    console.log(`Starting download of ${MAXITER} photos...`);
    isDownloading = true;
    toggleBeforeUnload(true); // 启用 beforeunload 事件
    GM_notification({
        text: 'Download started...',
        title: 'Facebook Bulk Downloader',
        timeout: 3000
    });
    batchDownload();
}

// 用户按下 Escape 键可随时停止下载
document.addEventListener('keydown', function (e) {
    if (e.key === 'Escape' && isDownloading) {
        console.log('Download stopped by user.');
        endDownload();
    }
});