您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Greasy Fork is available in English.
按章节打包下载漫画柜的资源
当前为
// ==UserScript== // @name 「漫画」打包下载(QQ 群:189574683) // @namespace https://www.wdssmq.com/ // @version 0.3 // @author 沉冰浮水 // @description 按章节打包下载漫画柜的资源 // @null ---------------------------- // @contributionURL https://github.com/wdssmq#%E4%BA%8C%E7%BB%B4%E7%A0%81 // @contributionAmount 5.93 // @null ---------------------------- // @link https://github.com/wdssmq/userscript // @link https://afdian.net/@wdssmq // @link http://greasyfork.icu/zh-CN/users/6865-wdssmq // @null ---------------------------- // @match https://www.manhuagui.com/comic/*/*.html // @require https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/comlink.min.js // @require https://cdn.jsdelivr.net/npm/[email protected]/dist/FileSaver.min.js // @run-at document-end // @grant GM_getValue // @grant GM_setValue // @grant GM_registerMenuCommand // @grant GM_xmlhttpRequest // ==/UserScript== /* jshint esversion:9 */ /* global Comlink saveAs */ // 本脚本综合以下项目实现 // http://greasyfork.icu/scripts/28410 // http://greasyfork.icu/scripts/375992 (() => { "use strict"; function $n(e) { return document.querySelector(e); } function $na(e) { return document.querySelectorAll(e); } // 网络请求 const get = (url, responseType = "json", retry = 2) => new Promise((resolve, reject) => { try { // console.log(navigator.userAgent); GM_xmlhttpRequest({ method: "GET", url, headers: { "User-Agent": navigator.userAgent, // If not specified, navigator.userAgent will be used. referer: "https://www.manhuagui.com/", }, responseType, onerror: (e) => { if (retry === 0) reject(e); else { console.warn("Network error, retry."); setTimeout(() => { resolve(get(url, responseType, retry - 1)); }, 1000); } }, onload: ({ status, response }) => { if (status === 200) resolve(response); else if (retry === 0) reject(`${status} ${url}`); else { console.warn(status, url); setTimeout(() => { resolve(get(url, responseType, retry - 1)); }, 500); } }, }); } catch (error) { reject(error); } }); const JSZip = (() => { const blob = new Blob( [ "importScripts(\"https://cdn.jsdelivr.net/npm/[email protected]/dist/umd/comlink.min.js\",\"https://cdn.jsdelivr.net/npm/[email protected]/dist/jszip.min.js\");class JSZipWorker{constructor(){this.zip=new JSZip}file(name,{data:data}){this.zip.file(name,data)}generateAsync(options,onUpdate){return this.zip.generateAsync(options,onUpdate).then(data=>Comlink.transfer({data:data},[data]))}}Comlink.expose(JSZipWorker);", ], { type: "text/javascript" }, ); const worker = new Worker(URL.createObjectURL(blob)); return Comlink.wrap(worker); })(); // 自定义压缩级别 let C_LEVEL = parseInt(GM_getValue("c_lv", "0")) || 0; GM_registerMenuCommand("Compression Level", () => { let num; do { num = prompt( `Please input a number (0-9) as compression level: 0: store (no compression) 1: lowest (best speed) ... 9: highest (best compression)`, C_LEVEL, ); if (num === null) return; num = parseInt(num.trim()); } while (isNaN(num) || num < 0 || num > 9); C_LEVEL = num; GM_setValue("c_lv", C_LEVEL); }); const getCompressionOptions = () => { if (C_LEVEL === 0) return {}; return { compression: "DEFLATE", compressionOptions: { level: C_LEVEL }, }; }; // 文件名补零 let FILENAME_LENGTH = parseInt(GM_getValue("filename_length", "2")) || 2; GM_registerMenuCommand("Filename Length", () => { let num; do { num = prompt( "Please input the minimum image filename length you want >=0, zeros will be padded to the start of filename when its length lower than this value:", FILENAME_LENGTH, ); if (num === null) return; num = parseInt(num); } while (num.toString() == "NaN" || num < 0); FILENAME_LENGTH = num; GM_setValue("filename_length", num); }); const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); let curImgUrl = ""; function fnGenUrl() { // 用于下载图片 const imgUrl = $n(".mangaFile").getAttribute("src"); // $n(".mangaFile").setAttribute("src",""); if (curImgUrl !== imgUrl) { console.log(imgUrl); curImgUrl = imgUrl; } // return encodeURI(imgUrl); return imgUrl; } function fnGenInfo() { const name = $n(".title h1 a").innerHTML; // 漫画名 const chapter = $n(".title h2").innerHTML; // 章节 const pages = $na("option").length; // 总页数 return { name, chapter, pages }; } const fnDownload = async ($btn = null) => { const info = fnGenInfo(); const cfName = `${info.name}_${info.chapter}`; info.done = 0; info.error = 0; info.bad = {}; console.log(info); // zip const zip = await new JSZip(); // const btnDownloadProgress = (curPage = 0) => { if ($btn) { $btn.innerHTML = `正在下载:${curPage} /${info.pages}`; } }; const btnCompressingProgress = (percent = 0) => { if ($btn) { $btn.innerHTML = percent == 100 ? "已完成√" : `正在压缩:${percent}`; } }; // 下载并添加到zip // page 从1开始 const dlPromise = async (url, page, threadID = 0) => { const fileName = ((i) => { return `${String(i).padStart(FILENAME_LENGTH, 0)}.jpg`; })(page); try { const data = await get(url, "arraybuffer"); await zip.file(fileName, Comlink.transfer({ data }, [data])); info.done++; } catch (e) { await zip.file(`${fileName}.bad.txt`, ""); info.bad[page] = `${url}`; info.error++; } }; for (let page = 0; page < info.pages; page++) { const url = fnGenUrl(); btnDownloadProgress(page + 1); await dlPromise(url, page + 1); await sleep(137); if (info.error) { alert("下载失败"); break; } $n("#next").click(); } // await multiThread(urls, dlPromise); return async () => { // info.compressing = true; // let lastZipFile = ""; const { data } = await zip.generateAsync( { type: "arraybuffer", ...getCompressionOptions() }, Comlink.proxy(({ percent, currentFile }) => { // if (lastZipFile !== currentFile && currentFile) { // lastZipFile = currentFile; // console.log(`Compressing ${percent.toFixed(2)}%`, currentFile); // } btnCompressingProgress(percent.toFixed(2)); info.compressingPercent = percent; }), ); console.log(info); // console.log("Done"); return { name: `${cfName}.zip`, data: new Blob([data]), error: info.error, }; }; }; // 创建开始按钮 let startDownload = document.createElement("a"); startDownload.id = "startDownload"; startDownload.className = "btn-red"; startDownload.innerHTML = "开始下载"; $n(".main-btn").appendChild(startDownload); startDownload.style.background = "#0077D1"; startDownload.style.cursor = "pointer"; startDownload.addEventListener("click", async () => { let curPage = parseInt($n("#page").innerHTML); if (curPage > 1) { alert("请从第一页开始下载"); return false; } const fnDL = await fnDownload(startDownload); const { data, name, error } = await fnDL(); if (!error) { saveAs(data, name); } }); // 单图查看 const setCurImgLink = () => { if ($n("#curimg")) { $n("#curimg").href = fnGenUrl(); return; } const $imgLink = document.createElement("a"); $imgLink.id = "curimg"; $imgLink.innerHTML = "查看单图"; $imgLink.className = "btn-red"; $imgLink.href = fnGenUrl(); $imgLink.target = "_blank"; $imgLink.style.background = "#0077D1"; $imgLink.style.cursor = "pointer"; $n(".main-btn").insertBefore($imgLink, $n("#viewList")); }; setCurImgLink(); window.addEventListener("hashchange", () => { setCurImgLink(); }); })();