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