Greasy Fork

ProQuest Document Downloader

Download documents from ProQuest search results

目前为 2024-12-13 提交的版本。查看 最新版本

// ==UserScript==
// @name         ProQuest Document Downloader
// @namespace    http://tampermonkey.net/
// @version      0.1
// @license      MIT
// @description  Download documents from ProQuest search results
// @author       powcai
// @match        https://www.proquest.com/*
// @grant        GM_xmlhttpRequest
// @grant        GM_addStyle
// @run-at       document-end
// @connect      *
// ==/UserScript==

(function() {
    'use strict';

    // 添加样式
    GM_addStyle(`
        .download-all-btn {
            position: fixed;
            top: 20px;
            right: 20px;
            background-color: #4CAF50;
            color: white;
            padding: 10px 20px;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            z-index: 9999;
        }
        .single-download-btn {
            background-color: #2196F3;
            color: white;
            padding: 5px 10px;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            margin: 5px;
        }
        .download-status {
            color: #666;
            margin-left: 10px;
            font-size: 12px;
        }
    `);

    // 下载单个文档
    async function downloadDocument(downloadUrl, statusElement) {
        try {
            if (statusElement) {
                statusElement.textContent = '准备下载...';
            }

            return new Promise((resolve, reject) => {
                GM_xmlhttpRequest({
                    method: 'GET',
                    url: downloadUrl,
                    responseType: 'blob',
                    onload: function(response) {
                        if (response.status === 200) {
                            const blob = new Blob([response.response], { type: 'application/pdf' });
                            const url = window.URL.createObjectURL(blob);
                            const a = document.createElement('a');
                            a.href = url;
                            a.download = `proquest-doc-${Date.now()}.pdf`;
                            document.body.appendChild(a);
                            a.click();
                            window.URL.revokeObjectURL(url);
                            a.remove();

                            if (statusElement) {
                                statusElement.textContent = '下载完成';
                                statusElement.style.color = '#4CAF50';
                            }
                            resolve();
                        } else {
                            if (statusElement) {
                                statusElement.textContent = '下载失败: ' + response.status;
                                statusElement.style.color = '#f44336';
                            }
                            reject(new Error('下载失败: ' + response.status));
                        }
                    },
                    onerror: function(error) {
                        console.error('下载请求失败:', error);
                        if (statusElement) {
                            statusElement.textContent = '下载失败: 网络错误';
                            statusElement.style.color = '#f44336';
                        }
                        reject(error);
                    }
                });
            });
        } catch (error) {
            console.error('下载过程出错:', error);
            if (statusElement) {
                statusElement.textContent = '下载失败: ' + error.message;
                statusElement.style.color = '#f44336';
            }
            throw error;
        }
    }

    // 添加下载按钮到每个搜索结果
    function addDownloadButtons() {
        const resultItems = document.querySelectorAll('li.resultItem');
        resultItems.forEach(item => {
            // 检查是否已经添加了下载按钮

            if (item.querySelector('.single-download-btn')) {
                return;
            }

            const pdfLink = item.querySelector('a[href*="fulltextPDF"]');

            if (!pdfLink) return;


            const buttonContainer = document.createElement('div');
            buttonContainer.style.display = 'flex';
            buttonContainer.style.alignItems = 'center';

            const downloadBtn = document.createElement('button');
            downloadBtn.className = 'single-download-btn';
            downloadBtn.textContent = '下载文档';

            const status = document.createElement('span');
            status.className = 'download-status';

            buttonContainer.appendChild(downloadBtn);
            buttonContainer.appendChild(status);
            item.appendChild(buttonContainer);

            downloadBtn.onclick = async () => {
                try {
                    const pdfPageUrl = pdfLink.href;
                    console.log("pdfPageUrl", pdfPageUrl)
                    const response = await fetch(pdfPageUrl);
                    const html = await response.text();
                    const parser = new DOMParser();
                    const doc = parser.parseFromString(html, 'text/html');
                    const downloadLink = doc.querySelector('a.pdf-download[download="ProQuestDocument.pdf"]');
                    if (downloadLink) {
                        await downloadDocument(downloadLink.href, status);
                    } else {
                        throw new Error('找不到PDF下载链接');
                    }
                } catch (error) {
                    console.error('单个文档下载失败:', error);
                    status.textContent = '下载失败: ' + error.message;
                    status.style.color = '#f44336';
                }
            };
        });
    }

    // 添加批量下载按钮
    function addBatchDownloadButton() {
        if (document.querySelector('.download-all-btn')) {
            return;
        }

        const batchButton = document.createElement('button');
        batchButton.className = 'download-all-btn';
        batchButton.textContent = '批量下载全部';
        document.body.appendChild(batchButton);

        batchButton.onclick = async () => {
            const resultItems = document.querySelectorAll('li.resultItem');
            let delay = 0;

            for (const item of resultItems) {
                const pdfLink = item.querySelector('a[href*="fulltextPDF"]');
                console.log(pdfLink)
                if (!pdfLink) continue;

                const status = item.querySelector('.download-status') || document.createElement('span');
                status.className = 'download-status';
                item.appendChild(status);

                setTimeout(async () => {
                    try {
                        const pdfPageUrl = pdfLink.href;
                        const response = await fetch(pdfPageUrl);
                        const html = await response.text();
                        const parser = new DOMParser();
                        const doc = parser.parseFromString(html, 'text/html');
                        const downloadLink = doc.querySelector('a.pdf-download[download="ProQuestDocument.pdf"]');
                        if (downloadLink) {
                            await downloadDocument(downloadLink.href, status);
                        } else {
                            throw new Error('找不到PDF下载链接');
                        }
                    } catch (error) {
                        console.error('批量下载过程中出错:', error);
                        status.textContent = '下载失败: ' + error.message;
                        status.style.color = '#f44336';
                    }
                }, delay);

                delay += 2000; // 每个下载间隔2秒
            }
        };
    }

    // 监听页面变化
    const observer = new MutationObserver((mutations) => {
        for (const mutation of mutations) {
            if (mutation.addedNodes.length) {
                addDownloadButtons();
                addBatchDownloadButton();
            }
        }
    });

    // 初始化
    function initialize() {
        addDownloadButtons();
        addBatchDownloadButton();
        observer.observe(document.body, {
            childList: true,
            subtree: true
        });
    }

    // 页面加载完成后初始化
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', initialize);
    } else {
        initialize();
    }
})();