您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
帮助你直接下载国自然结题报告(userscript版)
当前为
// ==UserScript== // @name NSFC conclusion downloader // @namespace https://blog.rhilip.info/ // @version 0.1 // @description 帮助你直接下载国自然结题报告(userscript版) // @author Rhilip // @match http://output.nsfc.gov.cn/conclusionProject/* // @require https://unpkg.com/jspdf@latest/dist/jspdf.umd.min.js // @require https://unpkg.com/axios/dist/axios.min.js // ==/UserScript== (function() { 'use strict'; // 从 jspdf 库中获得jsPDF const { jsPDF } = jspdf function asyncImageLoader(url){ return new Promise((resolve, reject) => { var image = new Image() image.src = url image.onload = () => resolve(image) image.onerror = () => reject(new Error('could not load image')) }) } function cleanFilename(filename) { return filename.replace(/[:\/]/ig, '_').replace(/\x00/ig,'_').replace(/[\n\\\*><?\"|\t]/ig,'') } /** * @param obj - { * sel: 'a', // the selector you want to wait for (optional) * context: document.body, // scope of search for selector or mutations (optional, default document.body) * stop: true, // stop waiting after first result (optional, default false) * mode: 'M', // M to use mutation observer, S to use setInterval (optional, default M) * onchange: func, // if using mode 'M' this function will be called whenever mutation handler triggers * onmatch: func, // if selector is specified function will be called for each match with element as parameter * config: { attributes: true } // if using mode 'M' this object will override settings passed to mutation observer * } */ function waitForElems(obj) { var tick; var id = 'fke' + Math.floor(Math.random() * 12345); var type = window.MutationObserver ? (obj.mode || 'M') : 'S'; var lastMutation = Date.now(); var lastCall = Date.now(); var context = obj.context || document.body; var sel = obj.sel; var config = obj.config || { subtree: true, childList: true }; var onChange = obj.onchange; var queuedCall; function throttle(func) { var now = Date.now(); clearTimeout(queuedCall); // less than 100ms since last mutation if (now - lastMutation < 100) { // 500ms or more since last query if (now - lastCall >= 500) { func(); } else { queuedCall = setTimeout(func, 100); } } else { func(); } lastMutation = now; } function findElem(sel) { lastCall = Date.now(); var found = [].filter.call(context.querySelectorAll(sel), function(elem) { return elem.dataset[id] !== 'y'; }); if (found.length > 0) { if (obj.stop) { type === 'M' ? tick.disconnect() : clearInterval(tick); } found.forEach(function(elem) { elem.dataset[id] = 'y'; obj.onmatch(elem); }); } } if (type === 'M') { tick = new MutationObserver(function() { if (sel) throttle.call(null, findElem.bind(null, sel)); if (onChange) onChange.apply(this, arguments); }); tick.observe(context, config); } else { tick = setInterval(findElem.bind(null, sel), 300); } if (sel) findElem(sel); return { type: type, stop: function() { if (type === 'M') { tick.disconnect(); } else { clearInterval(tick); } }, resume: function() { if (type === 'M') { tick.observe(context, config); } else { tick = setInterval(findElem.bind(null, sel), 300); } } }; } // 由于页面是动态加载的,所以我们需要等我们需要的元素加载出来再添加交互逻辑 waitForElems({ sel: '#conclusion-report-tab > h3', onmatch: () => { $('#conclusion-report-tab > h3').before('<button id="download_report" type="button" class="btn btn-link pull-right">(下载全文PDF)</button>') const downloadBtn = $('#download_report') downloadBtn.click((async () => { downloadBtn.prop('disabled', true) // 获得项目信息: 编号(加密后)、批准号、项目名称 const dependUintID = location.pathname.match(/conclusionProject\/(.+)/)[1] const projectID = $('#basic-tab > div:nth-child(1) > div.col-md-10').text() const projectName = $('#basic-tab > div:nth-child(2) > div.col-md-10').text() // 准备 jsPDF 对象 const doc = new jsPDF(); doc.deletePage(1); // 删除第一页 let i = 1; let should_loop = true; while (should_loop) { downloadBtn.text(`正在下载第 ${i} 页`) const postData = new URLSearchParams({id: dependUintID, index: i}); const req = await axios.post('http://output.nsfc.gov.cn/baseQuery/data/completeProjectReport', postData); const image = await asyncImageLoader(req.data.data.url) doc.addPage([image.width, image.height], image.width < image.height ? 'p' : 'l'); doc.addImage(image, "JPEG", 0, 0, image.width, image.height); should_loop = req.data.data.hasnext !== false; i++; } downloadBtn.text('正在生成PDF') doc.save(`${projectID} ${projectName}.pdf`) downloadBtn.text('下载完成') downloadBtn.prop('disabled', false) })) } }) })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址