您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
把文泉学堂的书籍下载成 PDF 文件。
// ==UserScript== // @name 文泉学堂保护装置 // @namespace http://tampermonkey.net/ // @version 2025-09-22 // @description 把文泉学堂的书籍下载成 PDF 文件。 // @author RebelPotato // @match https://lib-tsinghua.wqxuetang.com/* // @icon https://www.google.com/s2/favicons?sz=64&domain=wqxuetang.com // @grant none // @run-at document-start // @license Unlicense // ==/UserScript== // This is free and unencumbered software released into the public domain. // For more information, please refer to <https://unlicense.org/> const vault = {}; vault.log = console.log; const aCanvas = document.createElement("canvas"); const aCtx = aCanvas.getContext("2d"); vault.drawImage = Object.getPrototypeOf(aCtx).drawImage; window.revert = () => { console.log = vault.log; Object.getPrototypeOf(aCtx).drawImage = vault.drawImage; }; async function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } async function downloadPage(page, scale) { page.scrollIntoView(); let imgs; while (1) { imgs = [...page.getElementsByClassName("plg")[0].childNodes]; if (imgs.length >= 6) break; await sleep(500); } await sleep(1000 * (1 + Math.random())); const data = imgs.map((img) => ({ img, width: img.naturalWidth, height: img.naturalHeight, left: parseFloat(img.style.left.slice(0, -2)), })); data.sort((a, b) => a.left - b.left); let currentOffset = 0; data.forEach((item) => { item.offset = currentOffset; currentOffset += item.width; }); const imgWidth = currentOffset; const imgHeight = Math.max(...data.map((d) => d.height)); vault.log(`Page size: ${imgWidth}x${imgHeight}, preparing canvas...`); const canvas = document.createElement("canvas"); const ctx = canvas.getContext("2d"); canvas.width = imgWidth * scale; canvas.height = imgHeight * scale; const drawImage = vault.drawImage.bind(ctx); for (const d of data) { drawImage(d.img, d.offset * scale, 0, d.width * scale, d.height * scale); } return { width: canvas.width, height: canvas.height, url: canvas.toDataURL("image/webp", 1), }; } window.dl = async function main(start, end, scale = 1.0) { revert(); await new Promise((res) => { if (window.jspdf) return res(); const script = document.createElement("script"); script.src = "https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"; script.onload = res; document.body.appendChild(script); }); if (!window.jspdf) return; const { jsPDF } = window.jspdf; // get page count const pb = document.getElementById("pb"); let pages = [...pb.childNodes].filter( (e) => e instanceof HTMLDivElement && e.hasAttribute("index") ); pages = pages.slice(start, end); let doc; for (let i = 0; i < pages.length; i++) { vault.log(`Processing page ${i + 1}/${pages.length}`); const img = await downloadPage(pages[i], scale); vault.log( `Adding page ${i + 1}/${pages.length}: ${img.width}x${img.height}` ); if (!doc) doc = new jsPDF({ format: [img.width, img.height], unit: "px" }); else doc.addPage([img.width, img.height]); doc.addImage(img.url, "WEBP", 0, 0, img.width, img.height); } const title = document.querySelector(".read-header-name").innerText; vault.log(`Saving PDF: as {title}.pdf`); doc.save(title + ".pdf"); };
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址