// ==UserScript== // @name 知网论文PDF批量下载(正式版) // @namespace wujiaxin1949l@gmail.com // @version 1.1 // @description 在知网搜索论文后论文名字左侧选择你想要下载的论文,在下载小窗口点击“开始批量下载”即可。支持重复下载检测,窗口随标题长度自适应展开 // @author Vachel // @match *://*.cnki.net/* // @grant GM_xmlhttpRequest // @grant GM_download // @license MIT // @run-at document-idle // @downloadURL https://update.greasyfork.icu/scripts/571678/%E7%9F%A5%E7%BD%91%E8%AE%BA%E6%96%87PDF%E6%89%B9%E9%87%8F%E4%B8%8B%E8%BD%BD%28%E6%AD%A3%E5%BC%8F%E7%89%88%29.user.js // @updateURL https://update.greasyfork.icu/scripts/571678/%E7%9F%A5%E7%BD%91%E8%AE%BA%E6%96%87PDF%E6%89%B9%E9%87%8F%E4%B8%8B%E8%BD%BD%28%E6%AD%A3%E5%BC%8F%E7%89%88%29.meta.js // ==/UserScript== (function() { 'use strict'; let isDragging = false; let currentX, currentY, initialX, initialY, xOffset = 0, yOffset = 0; const downloadHistory = new Set(); const statusUpdater = { _selectedCount: 0, _isDownloading: false, setCount: function(count) { this._selectedCount = count; this.render(); }, setDownloading: function(active) { this._isDownloading = active; this.render(); }, setComplete: function() { const btn = document.getElementById('apple-start-btn'); if (btn) { btn.style.background = "#28c840"; btn.innerText = "✓ 搬运完毕"; setTimeout(() => { this._isDownloading = false; this.render(); }, 2500); } }, render: function() { const statusDiv = document.getElementById('apple-status'); const btn = document.getElementById('apple-start-btn'); if (!statusDiv || !btn || this._isDownloading) return; statusDiv.innerHTML = `已选择 ${this._selectedCount} 篇文献`; btn.disabled = this._selectedCount === 0; btn.style.background = this._selectedCount === 0 ? "rgba(0,0,0,0.05)" : "#0071e3"; btn.style.color = this._selectedCount === 0 ? "#86868b" : "white"; btn.innerText = "开始批量下载"; } }; /* --- UI 部分保持原样 --- */ function showAppleConfirm(duplicates, checkedElements) { if (document.getElementById('apple-confirm-overlay')) return; const overlay = document.createElement('div'); overlay.id = 'apple-confirm-overlay'; overlay.setAttribute('style', `position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.2); backdrop-filter:blur(4px); z-index:2147483647; display:flex; align-items:center; justify-content:center;`); const dialog = document.createElement('div'); dialog.setAttribute('style', `width: 320px; max-height: 80vh; background: rgba(255,255,255,0.85); backdrop-filter: blur(30px) saturate(180%); border-radius: 22px; box-shadow: 0 20px 60px rgba(0,0,0,0.2); display: flex; flex-direction: column; animation: applePop 0.3s cubic-bezier(0.34, 1.56, 0.64, 1); overflow: hidden; border: 0.5px solid rgba(255,255,255,0.4);`); dialog.innerHTML = `
⚠️

发现重复项目

以下文献已在本次会话中下载过:

${duplicates.map(t => `
${t}
`).join('')}
`; overlay.appendChild(dialog); document.body.appendChild(overlay); document.getElementById('apple-cancel-task').onclick = () => overlay.remove(); document.getElementById('apple-skip-task').onclick = () => { overlay.remove(); const freshItems = checkedElements.filter(box => { const title = box.closest('tr').querySelector('a.fz14')?.innerText.trim(); return !downloadHistory.has(title); }); processBatch(freshItems); }; } function initAppleUI() { if (document.getElementById('apple-manager')) return; const manager = document.createElement('div'); manager.id = 'apple-manager'; manager.setAttribute('style', `position:fixed; top:100px; right:30px; width:200px; z-index:99999; background:rgba(255,255,255,0.7); backdrop-filter:blur(20px) saturate(180%); border-radius:18px; border:1px solid rgba(255,255,255,0.4); box-shadow:0 8px 32px rgba(0,0,0,0.1); font-family:-apple-system,BlinkMacSystemFont,sans-serif; overflow:hidden;`); manager.innerHTML = `
CNKI MASTER
等待选取...
`; document.body.appendChild(manager); const style = document.createElement("style"); style.innerText = `@keyframes applePop { from { transform:scale(1.1); opacity:0; } to { transform:scale(1); opacity:1; } }`; document.head.appendChild(style); const handle = document.getElementById('apple-handle'); handle.onmousedown = (e) => { initialX = e.clientX - xOffset; initialY = e.clientY - yOffset; isDragging = true; }; window.onmousemove = (e) => { if (isDragging) { currentX = e.clientX - initialX; currentY = e.clientY - initialY; xOffset = currentX; yOffset = currentY; manager.style.transform = `translate3d(${currentX}px, ${currentY}px, 0)`; } }; window.onmouseup = () => { isDragging = false; }; setInterval(() => { const count = document.querySelectorAll('input.cbItem:checked').length; statusUpdater.setCount(count); }, 800); document.getElementById('apple-start-btn').onclick = function() { const checked = Array.from(document.querySelectorAll('input.cbItem:checked')); const titlesInThisBatch = checked.map(box => box.closest('tr').querySelector('a.fz14')?.innerText.trim()); const duplicates = titlesInThisBatch.filter(t => downloadHistory.has(t)); if (duplicates.length > 0) showAppleConfirm(duplicates, checked); else processBatch(checked); }; } /* --- 核心修复:改进的下载逻辑 --- */ function processBatch(elements) { if (elements.length === 0) return; statusUpdater.setDownloading(true); const btn = document.getElementById('apple-start-btn'); elements.forEach((box, i) => { const tr = box.closest('tr'); const linkTag = tr.querySelector('a.fz14') || tr.querySelector('a[href*="detail"]'); const rawTitle = linkTag?.innerText.trim(); setTimeout(() => { btn.innerText = `处理中 ${i+1}/${elements.length}`; GM_xmlhttpRequest({ method: "GET", url: linkTag.href, headers: { "Referer": window.location.href }, // 模拟真实来源 onload: (res) => { const doc = new DOMParser().parseFromString(res.responseText, 'text/html'); // 获取 PDF 下载链接 const pdfUrl = doc.querySelector('#pdfDown')?.href || doc.querySelector('.btn-dlpdf a')?.href; if (pdfUrl) { // 修复方案:放弃 GM_download,改用模拟真实点击 // 这样 IDM 能够正确截获下载流,且 Referer 不会丢失 const a = document.createElement('a'); a.href = pdfUrl; a.style.display = 'none'; document.body.appendChild(a); a.click(); downloadHistory.add(rawTitle); setTimeout(() => a.remove(), 1000); } if (i === elements.length - 1) statusUpdater.setComplete(); } }); }, i * 2500); // 增加间隔至 2.5s,提高知网在高频请求下的稳定性 }); } setTimeout(initAppleUI, 1000); })();