// ==UserScript== // @name 笔趣阁下载器 // @namespace http://tampermonkey.net/ // @version 0.3.8 // @description 可在笔趣阁下载小说(TXT格式),在小说目录页面使用。(仅供交流,可能存在bug)(已测试网址:beqege.cc|bigee.cc|bqgui.cc|bbiquge.la|3bqg.cc|xbiqugew.com) // @author Yearly // @match https://www.beqege.cc/*/ // @match https://www.bigee.cc/book/*/ // @match https://www.bqgui.cc/book/*/ // @match https://www.3bqg.cc/book/*/ // @match https://www.bbiquge.la/*/ // @match https://www.xbiqugew.com/book/*/ // @match https://www.beqege.com/*/ // @match https://www.bqg78.cc/book/*/ // @match https://www.biquge.tw/book/*/ // @license GPL-3.0 // @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 https://update.greasyfork.icu/scripts/500170/%E7%AC%94%E8%B6%A3%E9%98%81%E4%B8%8B%E8%BD%BD%E5%99%A8.user.js // @updateURL https://update.greasyfork.icu/scripts/500170/%E7%AC%94%E8%B6%A3%E9%98%81%E4%B8%8B%E8%BD%BD%E5%99%A8.meta.js // ==/UserScript== (function() { GM_addStyle(` #fetchContentModal { display: block; 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: 500px; text-align: center; } #fetchContentModal h3{ margin: 1.3em; } #fetchContentModal label{ display: block; font-size: 14px; } #fetchContentModal input[type="number"] { width: auto; margin: 2px 3px; text-align: center; -moz-appearance: textfield; appearance: textfield; } input[type="number"]::-webkit-inner-spin-button, input[type="number"]::-webkit-outer-spin-button { -webkit-appearance: inner-spin-button; opacity: 1; } #fetchContentModal button { width: 100%; margin: 10px 0; } #fetchContentModal #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; } #fetchContentModal td { white-space: nowrap; overflow: hidden; } `); const modalHtml = `
`; document.body.insertAdjacentHTML('beforeend', modalHtml); // 获取元素 const modal = document.getElementById('fetchContentModal'); const startRangeInput = document.getElementById('_startRange'); const finalRangeInput = document.getElementById('_finalRange'); const startTitle = document.getElementById('_startRange_title'); const finalTitle = document.getElementById('_finalRange_title'); const fetchButton = document.getElementById('fetchContentButton'); const progressBar = document.getElementById('fetchContentProgress').firstElementChild; const downlink = document.getElementById('_downlink'); const warnInfo = document.getElementById('_warn_info'); const bookInfo = document.getElementById('_book_info'); const fetcClose = document.getElementById('fetcModalClose'); let booktitle = null; let tocDiv = null; let chapters = null; let startIndex, finalIndex; function downloadMenu() { modal.style.display = 'block'; tocDiv = document.querySelector("#list") || document.querySelector(".listmain") || document.querySelector(".list-chapter"); if(tocDiv.querySelector('dl center.clear')) { chapters = document.querySelectorAll("dl center.clear ~ dd > a[href]") } else { chapters = tocDiv.querySelectorAll("dl dd > a[href]") } if(!chapters.length) { chapters = document.querySelectorAll("div.list-chapter > div.booklist > ul > li > a[href]") } startRangeInput.max = chapters.length; finalRangeInput.max = chapters.length; startIndex = 0; finalIndex = chapters.length - 1; finalRangeInput.value = chapters.length; startTitle.innerText = chapters[startIndex].innerText; finalTitle.innerText = chapters[finalIndex].innerText; const title = document.querySelector("#maininfo #info h1") || document.querySelector(".info h1") || document.querySelector("h1") ; if(title) booktitle = title.innerText; else booktitle = document.title; bookInfo.innerText=`当前小说:《${booktitle}》,共 ${chapters.length} 章。` warnInfo.innerText=`设置范围后点击开始下载,并稍作等待。\n若章节过多下载卡住,可尝试减小章节范围分次下载。` if(document.querySelector('button#downloadMenuBtn')) { document.querySelector('button#downloadMenuBtn').hidden=true; } } if (document.querySelector("h1")) { let downloadMenuBtn = document.createElement("button"); downloadMenuBtn.innerText = "下载" downloadMenuBtn.id="downloadMenuBtn" downloadMenuBtn.style="padding:2px 10px; margin:auto 10px; font-size:15px; background:#ccF8;" document.querySelector("h1").append(downloadMenuBtn) downloadMenuBtn.addEventListener('click', downloadMenu); } GM_registerMenuCommand('小说下载工具', downloadMenu); fetcClose.addEventListener('click', async () => { modal.style.display = 'none'; if(document.querySelector('button#downloadMenuBtn')) { document.querySelector('button#downloadMenuBtn').hidden=false; } }); startRangeInput.addEventListener('input', function() { let val = parseInt(startRangeInput.value) if (!isNaN(val)) { if (val < 1) {val = 1;} if (val > chapters.length) {val = chapters.length;} startRangeInput.value = val; startIndex = parseInt(val) - 1; startTitle.innerText = chapters[startIndex].innerText; } }); finalRangeInput.addEventListener('input', function() { let val = parseInt(finalRangeInput.value) if (!isNaN(val)) { if (val < 1) {val = 1;} if (val > chapters.length) {val = chapters.length;} finalRangeInput.value = val; finalIndex = parseInt(val) - 1; finalTitle.innerText = chapters[finalIndex].innerText; } }); fetchButton.addEventListener('click', async () => { downlink.innerText = ""; downlink.href = null; downlink.download = null; fetchButton.disabled = true; if (startIndex > finalIndex) { let temp0 = startIndex; let temp1 = finalIndex; startIndex = temp1; finalIndex = temp0; startRangeInput.value = startIndex+1; startTitle.innerText = chapters[startIndex].innerText; finalRangeInput.value = finalIndex+1; finalTitle.innerText = chapters[finalIndex].innerText; } const links = document.querySelectorAll("dl dd > a[href], div.list-chapter > div.booklist > ul > li > a[href]") const selectedLinks = Array.from(links).slice(startIndex, finalIndex+1); if (!booktitle){ booktitle = document.title; } const results = []; const totalLinks = selectedLinks.length; let completedRequests = 0; const retry = []; const delay = ms => new Promise(resolve => setTimeout(resolve, ms)); let queue = 0; async function fetchContent(url, link) { let allContent = ''; let title = ''; async function fetchPage(pageUrl) { const response = await fetch(pageUrl, { method: "GET" }); if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } let text = ''; const contentType = response.headers.get('Content-Type'); if (contentType) { let charset = 'utf-8'; // 默认编码 const charsetMatch = contentType && contentType.match(/charset=([^;]+)/i); if (charsetMatch) { charset = charsetMatch[1].toLowerCase(); } const arrayBuffer = await response.arrayBuffer(); const decoder = new TextDecoder(charset); text = decoder.decode(new Uint8Array(arrayBuffer)); } else { text = await response.text(); } const parser = new DOMParser(); const doc = parser.parseFromString(text, 'text/html'); const contentDiv = doc.querySelector('div#content') || doc.querySelector('#chaptercontent') || doc.querySelector('.content'); if (contentDiv) { contentDiv.querySelectorAll('div#device').forEach(function(web_ad) { web_ad.remove(); }); contentDiv.querySelectorAll('p.readinline > a[href*="javascript:"]').forEach(function(web_op) { web_op.remove(); }); contentDiv.innerHTML = contentDiv.innerHTML.replaceAll('