Greasy Fork

Facebook Photos Bulk Downloader (Background Support)

Bulk download Facebook album photos in full resolution, supports background downloading

目前为 2024-11-14 提交的版本。查看 最新版本

// ==UserScript==
// @name         Facebook Photos Bulk Downloader (Background Support)
// @namespace    麦克
// @version      2.1.2
// @description  Bulk download Facebook album photos in full resolution, supports background downloading
// @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;
const isDebug = true;
let isDownloading = false;
let stopDownload = false;

// 防止页面自动刷新或导航导致下载中断
window.addEventListener('beforeunload', function (event) {
    if (isDownloading) {
        event.preventDefault();
        event.returnValue = '';
    }
});

// 监听 Facebook 异步导航并恢复下载
window.addEventListener('popstate', function () {
    if (isDownloading) {
        console.log('Page navigation detected, resuming download...');
        setTimeout(batchDownload, 1000);
    }
});

// 创建 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 });
})();

// 获取当前图片 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) {
        console.log('Download limit reached or stopped by user.');
        GM_notification({
            text: `Download completed: ${iter} photos`,
            title: 'Facebook Bulk Downloader',
            timeout: 5000
        });
        isDownloading = false;
        return;
    }

    const imgUrl = getImageUrl();
    if (imgUrl) {
        downloadImage(imgUrl, () => {
            iter++;
            if (clickNextImage()) {
                console.log(`Moving to image ${iter + 1}`);
                setTimeout(batchDownload, 1000); // 等待 1 秒后继续下载
            } else {
                console.log('No more images found or failed to click next.');
                GM_notification({
                    text: `Download completed: ${iter} photos`,
                    title: 'Facebook Bulk Downloader',
                    timeout: 5000
                });
                isDownloading = false;
            }
        });
    } else {
        console.error('Retry fetching image...');
        setTimeout(() => {
            if (!stopDownload) batchDownload();
        }, 1000);
    }
}

// 开始批量下载
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;
    GM_notification({
        text: 'Download started...',
        title: 'Facebook Bulk Downloader',
        timeout: 3000
    });
    batchDownload();
}

// 监听页面切换时继续执行
window.addEventListener('visibilitychange', function () {
    if (document.visibilityState === 'hidden' && isDownloading) {
        console.log('Running in the background...');
    } else if (document.visibilityState === 'visible' && isDownloading) {
        console.log('Resuming download...');
    }
});

// 用户随时可停止下载
document.addEventListener('keydown', function (e) {
    if (e.key === 'Escape' && isDownloading) {
        stopDownload = true;
        isDownloading = false;
        console.log('Download stopped by user.');
        GM_notification({
            text: 'Download stopped by user.',
            title: 'Facebook Bulk Downloader',
            timeout: 3000
        });
    }
});