您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
IEEE Paper Downloader is a Greasemonkey script that enables batch downloading of papers. It bypasses the IEEE Xplore's limit on downloading up to 10 papers at a time, allowing you to download more than 10 papers in one go.
// ==UserScript== // @name IEEE Paper Downloader // @namespace https://ieeexplore.ieee.org/ // @version 1.2 // @description IEEE Paper Downloader is a Greasemonkey script that enables batch downloading of papers. It bypasses the IEEE Xplore's limit on downloading up to 10 papers at a time, allowing you to download more than 10 papers in one go. // @author OccDeser // @match https://ieeexplore.ieee.org/*/proceeding* // @grant GM_xmlhttpRequest // @grant GM_download // @license MIT // ==/UserScript== const DOWNLOAD_INTERVAL = 1000; // Download interval in milliseconds const CSS = ` .paper-downloader { margin-left: 15px; margin-right: 15px; padding-top: 15px; padding-bottom: 15px; background-color: #f5f5f5; } .paper-downloader span { padding: 5px; } .ipd-modal-background { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.5); /* Gray background with 50% transparency */ display: flex; justify-content: center; /* Horizontal centering */ align-items: center; /* Vertical centering */ z-index: 999; /* Place modal on top */ flex-direction: column; } .ipd-modal-body { width: 75%; padding: 20px; background: #fff; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); } .ipd-modal-content { height: 450px; overflow-y: auto; } ` const HTML = ` <div class="paper-downloader"> <span> <xpl-conference-toc-dashboard> <strong class="text-base-md-lh"> IEEE Paper Downloader </strong> </xpl-conference-toc-dashboard> </span> <span> <xpl-conference-toc-dashboard> <strong class="text-base-md-lh" id="ipd-strong-countdown"> </strong> </xpl-conference-toc-dashboard> </span> <span> <xpl-export-search-results> <button class="xpl-toggle-btn" id="ipd-button-showall"> <a class="text-white"> Show All </a> </button> </xpl-export-search-results> </span> <span> <xpl-export-search-results> <button class="xpl-toggle-btn" id="ipd-button-select"> <a class="text-white"> Select </a> </button> </xpl-export-search-results> </span> <span> <xpl-export-search-results> <button class="xpl-toggle-btn" id="ipd-button-download"> <a class="text-white"> Download </a> </button> </xpl-export-search-results> </span> </div> ` var allPapers = {}; var selectedPapers = {}; const createModal = (content, onClose) => { const modalHtml = ` <div class="ipd-modal-background"> <div class="ipd-modal-body"> <div class="ipd-modal-content"> ${content} </div> <xpl-export-search-results> <button class="xpl-toggle-btn" id="ipd-modal-close"> <a class="text-white">Close</a> </button> </xpl-export-search-results> </div> </div> ` let modalElement = document.createElement('div'); modalElement.innerHTML = modalHtml; document.body.appendChild(modalElement); // Bind listener let modalCloseButton = document.getElementById('ipd-modal-close'); modalCloseButton.addEventListener('click', () => { modalElement.remove(); onClose(); }); } const downloadPapers = () => { const downloadLinks = []; for (let id in selectedPapers) { if (selectedPapers[id]) { let url = new URL("https://ieeexplore.ieee.org" + allPapers[id].href); const arnumber = url.searchParams.get('arnumber'); downloadLinks.push(`https://ieeexplore.ieee.org/stampPDF/getPDF.jsp?tp=&arnumber=${arnumber}&isBulkDownload=true`); } } console.log(downloadLinks); // Show download progress createModal( '<div id="ipd-modal-progress"></div>', () => { console.log('Modal closed'); } ); let progress = document.getElementById('ipd-modal-progress'); let progressCounter = 0; const progressInfo = (message) => { let messageBox = document.createElement('div'); messageBox.innerHTML = message; messageBox.style = "margin-bottom: 5px;"; progress.insertBefore(messageBox, progress.firstChild); } const progressTop = (message) => { let topMessageBox = document.getElementById('ipd-modal-progress-top'); if (topMessageBox) { topMessageBox.remove(); } let messageBox = document.createElement('div'); messageBox.id = 'ipd-modal-progress-top'; messageBox.innerHTML = message; messageBox.style = "margin-bottom: 5px; font-weight: bold;"; progress.insertBefore(messageBox, progress.firstChild); } progressInfo(`Downloading ${downloadLinks.length} papers...`); // Store downloaded content const downloadedContent = []; // Use GM_xmlhttpRequest to fetch link content const fetchContent = (url) => { let filename = new URL(url).searchParams.get('arnumber') + '.pdf'; return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: 'GET', url: url, responseType: 'arraybuffer', onload: response => resolve(response.response), onerror: error => reject(error), onprogress: progressEvent => { let size = progressEvent.loaded / 1024 / 1024; progressTop(`${filename} Downloading: ${size.toFixed(2)}MB`); } }); }); } // Iterate through download links and fetch content const fetchAndDownload = async () => { for (const link of downloadLinks) { try { let filename = new URL(link).searchParams.get('arnumber') + '.pdf'; const content = await fetchContent(link); downloadedContent.push({ filename: filename, content }); progressCounter++; progressInfo(`[${progressCounter}/${downloadLinks.length}] Fetched content from: ${link}`); progressTop(`${filename} Downloaded, continuing in ${DOWNLOAD_INTERVAL / 1000} seconds...`); await new Promise(resolve => setTimeout(resolve, DOWNLOAD_INTERVAL)); } catch (error) { console.error(`Error fetching content from link: ${error}`); } } // Compress all content into a single zip file and download const zip = new JSZip(); for (const item of downloadedContent) { zip.file(item.filename, item.content); } zip.generateAsync({ type: 'blob' }) .then(blob => { GM_download({ url: URL.createObjectURL(blob), name: 'papers.zip' }); }); } fetchAndDownload(); } const selectPapers = () => { const xpathExpression = '//div[@class="subid-container"]//xpl-access-type-icon/span[not(contains(@class, "locked"))]/../../../..'; let paperResults = document.evaluate(xpathExpression, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); if (paperResults.snapshotLength > 0) { let paperElement = paperResults.snapshotItem(0); let paperHref = paperElement.getElementsByTagName('xpl-view-pdf')[0].getElementsByTagName('a')[0].getAttribute('href'); let paperTitle = paperElement.getElementsByTagName('h2')[0].textContent; let id = 0 + '-' + paperTitle.slice(0, 16) + '-' + paperHref.slice(-8); let first_id = Object.keys(allPapers).filter((key) => key.startsWith('0'))[0]; // Check if the page has been updated if (Object.keys(allPapers).length !== paperResults.snapshotLength || id !== first_id) { allPapers = {}; selectedPapers = {}; for (let i = 0; i < paperResults.snapshotLength; i++) { let paperElement = paperResults.snapshotItem(i); let paperHref = paperElement.getElementsByTagName('xpl-view-pdf')[0].getElementsByTagName('a')[0].getAttribute('href'); let paperTitle = paperElement.getElementsByTagName('h2')[0].textContent; let id = i + '-' + paperTitle.slice(0, 16) + '-' + paperHref.slice(-8); allPapers[id] = { 'title': paperTitle, 'href': paperHref, 'element': paperElement }; selectedPapers[id] = true; } } } // Create modal createModal( '<form id="ipd-select-dynamic-form"></form>', () => { let counter = 0; for (let id in selectedPapers) { if (selectedPapers[id]) { counter++; } } console.log(`Selected ${counter} papers`); } ) // Create select form let dynamicForm = document.getElementById('ipd-select-dynamic-form'); let items = [] for (let id in allPapers) { items.push({ id, title: allPapers[id].title }); } items.forEach(function (item, _) { var checkbox = document.createElement('input'); checkbox.type = 'checkbox'; checkbox.name = item.title; checkbox.value = item.id; checkbox.checked = selectedPapers[item.id]; checkbox.addEventListener('change', function () { selectedPapers[checkbox.value] = checkbox.checked; }); var label = document.createElement('label'); label.appendChild(checkbox); var titleBox = document.createElement('span'); titleBox.appendChild(document.createTextNode(item.title)); titleBox.style = "margin-left: 5px;"; label.appendChild(titleBox); var itemDiv = document.createElement('div'); itemDiv.style = "margin-bottom: 5px;"; itemDiv.appendChild(label); dynamicForm.appendChild(itemDiv); }); } const showAll = () => { console.log("showAll"); // Get the current rowsPerPage const url = new URL(window.location.href); const current_rows = eval(url.searchParams.get('rowsPerPage')) // Get the total number of rows const xpathExpression = "//span[contains(., 'Showing')]/span[2]/text()"; const result = document.evaluate(xpathExpression, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); if (result.snapshotLength == 0) { console.log("Cannot find total rows"); return; } const total_rows = eval(result.snapshotItem(0).textContent); if (current_rows >= total_rows) { console.log("Already showing all"); return; } url.searchParams.set('rowsPerPage', total_rows.toString()); const modifiedURL = url.toString(); window.location.href = modifiedURL; } const bindListener = () => { let buttonSelect = document.getElementById('ipd-button-select'); let buttonDownload = document.getElementById('ipd-button-download'); let buttonShowAll = document.getElementById('ipd-button-showall'); buttonSelect.addEventListener('click', selectPapers); buttonDownload.addEventListener('click', downloadPapers); buttonShowAll.addEventListener('click', showAll); } (function () { 'use strict'; let mainElement = document.getElementById('xplMainContentLandmark'); if (mainElement) { // Insert CSS codes let style = document.createElement('style'); style.appendChild(document.createTextNode(CSS)); document.head.appendChild(style); // Insert HTML codes let optionHeader = document.createElement('div'); optionHeader.innerHTML = HTML; let firstChild = mainElement.firstChild; mainElement.insertBefore(optionHeader, firstChild); // Add event listener bindListener(); // Set the countdown let timerCounter = 0; let countDownTimer = setInterval(() => { let countDownElement = document.getElementById('ipd-strong-countdown'); timerCounter = timerCounter + 100; countDownElement.innerHTML = "Loading... " + timerCounter / 1000 + "s"; }, 100); // Wait for loading const loadPapers = () => { const xpathExpression = '//div[@class="subid-container"]//xpl-access-type-icon/span[not(contains(@class, "locked"))]/../../../..'; let paperResults = document.evaluate(xpathExpression, document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); if (paperResults.snapshotLength > 0) { clearInterval(countDownTimer); let countDownElement = document.getElementById('ipd-strong-countdown'); countDownElement.innerHTML = "Loading complete!"; } else { setTimeout(loadPapers, 100); return; } } setTimeout(loadPapers, 100); } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址