// ==UserScript== // @name 趣笔阁下载器 // @namespace http://tampermonkey.net/ // @version 0.1.3 // @description 可在趣笔阁下载小说,在小说目录页面使用,仅供交流,可能存在bug。 // @author Yearly // @match https://www.beqege.cc/*/ // @license MIT // @grant GM_registerMenuCommand // @grant GM_addStyle // @namespace https://greasyfork.org/scripts/500170 // @supportURL https://greasyfork.org/scripts/500170 // @homepageURL https://greasyfork.org/scripts/500170 // @icon https://www.beqege.cc/favicon.ico // @downloadURL none // ==/UserScript== (function() { // 添加自定义样式 GM_addStyle(` #fetchContentModal { border-radius: 10px; position: fixed; top: 40%; left: 50%; transform: translate(-50%, -50%); background: white; padding: 5px 20px 10px 20px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.5); z-index: 10000; width: 300px; text-align: center; } #fetchContentModal input[type="number"] { width: 30%; margin: 5px 0; text-align: center; } #fetchContentModal button { width: 100%; margin: 10px 0; } #fetchContentProgress { width: 100%; background: #f3f3f3; border: 1px solid #ccc; margin: 10px 0; } #fetchContentProgress div { width: 0; height: 20px; background: #4caf50; text-align: center; margin-left: 0; color: #960; white-space: nowrap; } `); // 创建悬浮窗 const modalHtml = ` `; document.body.insertAdjacentHTML('beforeend', modalHtml); // 获取元素 const modal = document.getElementById('fetchContentModal'); const startRangeInput = document.getElementById('_startRange'); const endRangeInput = document.getElementById('_endRange'); const fetchButton = document.getElementById('fetchContentButton'); const progressBar = document.getElementById('fetchContentProgress').firstElementChild; const downlink = document.getElementById('_downlink'); const warnInfo = document.getElementById('_warn_info'); const fetcClose = document.getElementById('fetcModalClose'); // 注册菜单命令 GM_registerMenuCommand('小说下载工具', () => { modal.style.display = 'block'; endRangeInput.max = document.querySelectorAll("#list > dl > dd > a").length; warnInfo.innerText=`当前小说共 ${endRangeInput.max} 章,设置范围后开始下载。\n 若章节范围较大耗时会较长,请稍作等待。` }); fetcClose.addEventListener('click', async () => { modal.style.display = 'none'; }); // 下载 fetchButton.addEventListener('click', async () => { const startRange = parseInt(startRangeInput.value, 10) - 1; const endRange = parseInt(endRangeInput.value, 10); // Step 1: 获取当前网页中的 document.querySelectorAll("#list > dl > dd > a") const links = document.querySelectorAll("#list > dl > dd > a"); // Step 2: 获取指定范围的链接 const selectedLinks = Array.from(links).slice(startRange, endRange); // 数组是从0开始计数的,所以startRange-1对应第startRange个元素 const title = document.title; // Step 3: 逐个去GET该链接内容并解析 let results = document.querySelector("#maininfo #info").innerText || title || ''; results+=`\n\n下载章节范围:${startRange} ~ ${endRange}\n` results+="\n-----------------------\n" for (let i = 0; i < selectedLinks.length; i++) { const link = selectedLinks[i]; const url = link.href; results += "\n ## " + link.innerText + '\n'; try { const response = await fetch(url); const text = await response.text(); const parser = new DOMParser(); const doc = parser.parseFromString(text, 'text/html'); doc.querySelectorAll('div#content > :not(div#device)').forEach(function (item) { const content = item.innerText || ''; results += content + '\n'; }); } catch (error) { results += `Error fetching ${url}:` + error + '\n'; } // 更新进度条 progressBar.style.width = `${((i + 1) / selectedLinks.length) * 100}%`; progressBar.textContent = `${i + 1} / ${selectedLinks.length}`; } // Step 4: 创建并下载包含所有内容的文件 const blob = new Blob([results], { type: 'text/plain' }); downlink.innerText="加载完成后,若未开始自动下载,点击这里" downlink.href = URL.createObjectURL(blob); downlink.download = `${title}_${startRange}_${endRange}.txt`; downlink.click(); }); })();