您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
将网页漫画下载下来方便导入墨水屏电子书进行阅读,目前仅适用于如漫画(https://m.rumanhua.com/)
当前为
// ==UserScript== // @name 网页漫画下载为epub/mobi/pdf等电子书格式 // @namespace http://tampermonkey.net/ // @version 1.1.3 // @description 将网页漫画下载下来方便导入墨水屏电子书进行阅读,目前仅适用于如漫画(https://m.rumanhua.com/) // @author MornLight // @match https://m.rumanhua.com/* // @icon https://www.google.com/s2/favicons?sz=64&domain=greasyfork.org // @grant GM_xmlhttpRequest // @require https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js // @run-at document-end // @license MIT // @supportURL https://duanmorningsir.github.io/ // ==/UserScript== (function () { 'use strict'; // 创建下载按钮和输入框 function createDownloadButton() { const container = document.createElement('div'); container.style.position = 'fixed'; container.style.bottom = '20px'; container.style.right = '20px'; container.style.zIndex = '1000'; container.style.display = 'flex'; container.style.flexDirection = 'column'; container.style.gap = '12px'; container.style.backgroundColor = 'rgba(255, 255, 255, 0.9)'; container.style.padding = '15px'; container.style.borderRadius = '5px'; container.style.boxShadow = '0 0 10px rgba(0,0,0,0.1)'; // 获取总页数 const totalPages = document.querySelectorAll('div.chapter-img-box').length; // 起始页输入框 const startInput = document.createElement('input'); startInput.type = 'number'; startInput.min = '1'; startInput.max = totalPages; startInput.value = '1'; startInput.placeholder = `起始页(1-${totalPages})`; startInput.style.width = '120px'; startInput.style.padding = '8px'; startInput.style.border = '1px solid #ccc'; startInput.style.borderRadius = '5px'; startInput.style.textAlign = 'center'; startInput.style.fontSize = '14px'; // 结束页输入框 const endInput = document.createElement('input'); endInput.type = 'number'; endInput.min = '1'; endInput.max = totalPages; endInput.value = totalPages; // 默认设为最大页数 endInput.placeholder = `结束页(1-${totalPages})`; endInput.style.width = '120px'; endInput.style.padding = '8px'; endInput.style.border = '1px solid #ccc'; endInput.style.borderRadius = '5px'; endInput.style.textAlign = 'center'; endInput.style.fontSize = '14px'; // 添加输入验证 startInput.addEventListener('change', () => { const startVal = parseInt(startInput.value); const endVal = parseInt(endInput.value); if (startVal < 1) { alert('起始页不能小于1'); startInput.value = '1'; } else if (startVal > totalPages) { alert(`起始页不能大于总页数${totalPages}`); startInput.value = '1'; } else if (startVal > endVal) { alert('起始页不能大于结束页'); startInput.value = endVal; } }); endInput.addEventListener('change', () => { const startVal = parseInt(startInput.value); const endVal = parseInt(endInput.value); if (endVal > totalPages) { alert(`结束页不能大于总页数${totalPages}`); endInput.value = totalPages; } else if (endVal < startVal) { alert('结束页不能小于起始页'); endInput.value = startVal; } }); // 下载按钮 const downloadButton = document.createElement('button'); downloadButton.textContent = '下载指定范围漫画'; downloadButton.style.padding = '10px'; downloadButton.style.backgroundColor = '#007bff'; downloadButton.style.color = '#fff'; downloadButton.style.border = 'none'; downloadButton.style.borderRadius = '5px'; downloadButton.style.cursor = 'pointer'; // 全部下载按钮 const downloadAllButton = document.createElement('button'); downloadAllButton.textContent = '下载整个章节'; downloadAllButton.style.padding = '10px'; downloadAllButton.style.backgroundColor = '#28a745'; downloadAllButton.style.color = '#fff'; downloadAllButton.style.border = 'none'; downloadAllButton.style.borderRadius = '5px'; downloadAllButton.style.cursor = 'pointer'; // 添加事件监听 downloadButton.addEventListener('click', () => downloadComic(startInput.value, endInput.value)); downloadAllButton.addEventListener('click', () => downloadComic()); container.appendChild(startInput); container.appendChild(endInput); container.appendChild(downloadButton); container.appendChild(downloadAllButton); document.body.appendChild(container); } // 获取章节名称 function getChapterName() { const chapterNameElement = document.querySelector('.chaphead-name h1'); return chapterNameElement ? chapterNameElement.textContent.trim() : '未知章节'; } // 下载漫画 async function downloadComic(startPage, endPage) { const chapterName = getChapterName(); const chapterImgBoxes = document.querySelectorAll('div.chapter-img-box'); const totalPages = chapterImgBoxes.length; // 确定起始和结束页 const start = startPage ? parseInt(startPage, 10) : 1; const end = endPage ? parseInt(endPage, 10) : totalPages; // 验证页数 if (start > end || start < 1 || end > totalPages) { alert(`请输入有效的页数范围!(1-${totalPages})`); return; } // 创建 PDF 实例 const pdf = new jspdf.jsPDF(); // 并行下载图片 const downloadPromises = []; chapterImgBoxes.forEach((box, index) => { // 只下载指定范围内的图片 if (index + 1 >= start && index + 1 <= end) { const img = box.querySelector('img'); if (img && img.dataset.src) { const imgUrl = img.dataset.src; downloadPromises.push(downloadImage(imgUrl, index - start + 1, pdf, end - start + 1)); } } }); // 等待所有图片下载完成 await Promise.all(downloadPromises); // 保存 PDF 文件 const fileName = end === chapterImgBoxes.length && start === 1 ? `${chapterName}_全部.pdf` : `${chapterName}_${start}-${end}.pdf`; pdf.save(fileName); // 显示下载完成的提示 alert(`漫画《${chapterName}》第${start}至${end}页下载完成!`); } // 下载图片并添加到 PDF function downloadImage(url, index, pdf, maxImages) { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: 'GET', url: url, responseType: 'blob', onload: function (response) { try { const blob = response.response; const reader = new FileReader(); reader.onload = function (event) { const imgData = event.target.result; pdf.addImage(imgData, 'JPEG', 0, 0, pdf.internal.pageSize.getWidth(), pdf.internal.pageSize.getHeight()); if (index < maxImages - 1) { pdf.addPage(); } resolve(); }; reader.readAsDataURL(blob); } catch (error) { console.error('处理图片时出错:', error); reject(error); } }, onerror: function (error) { console.error('下载图片失败:', error); reject(error); } }); }); } // 创建下载按钮和输入框 createDownloadButton(); })();