您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
一鍵下載圖片 [壓縮下載/單圖下載] , json 數據創建 (還沒添加)
当前为
// ==UserScript== // @name Kemono Download Tool // @version 0.0.3 // @author HentiSaru // @description 一鍵下載圖片 [壓縮下載/單圖下載] , json 數據創建 (還沒添加) // @match *://kemono.su/* // @match *://*.kemono.su/* // @match *://kemono.party/* // @match *://*.kemono.party/* // @icon https://cdn-icons-png.flaticon.com/512/2381/2381981.png // @license MIT // @run-at document-end // @grant GM_addStyle // @grant GM_setValue // @grant GM_getValue // @grant GM_download // @grant GM_addElement // @grant GM_deleteValue // @grant GM_notification // @grant GM_xmlhttpRequest // @grant GM_registerMenuCommand // @require https://cdnjs.cloudflare.com/ajax/libs/jszip/3.7.1/jszip.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js // @namespace https://greasyfork.org/users/989635 // ==/UserScript== var CompressMode = GM_getValue("壓縮下載", []), ModeDisplay; (function() { const pattern = /^(https?:\/\/)?(www\.)?kemono\..+\/.+\/user\/.+\/post\/.+$/; if (pattern.test(window.location.href)) {setTimeout(ButtonCreation, 300)} GM_registerMenuCommand("🔁 切換下載模式", function() {DownloadModeSwitch()}, "C") GM_registerMenuCommand("📃 開啟當前頁面所有帖子", function() {OpenData()}, "O") })(); async function DownloadModeSwitch() { if (GM_getValue("壓縮下載", [])){ GM_setValue("壓縮下載", false); GM_notification({ title: "模式切換", text: "單圖下載模式", timeout: 2500 }); } else { GM_setValue("壓縮下載", true); GM_notification({ title: "模式切換", text: "壓縮下載模式", timeout: 2500 }); } location.reload(); } async function ButtonCreation() { GM_addStyle(` .File_Span { padding: 1rem; font-size: 20% !important; } .Download_Button { color: hsl(0, 0%, 45%); padding: 6px; border-radius: 8px; border: 2px solid rgba(59, 62, 68, 0.7); background-color: rgba(29, 31, 32, 0.8); font-family: Arial, sans-serif; } .Download_Button:hover { color: hsl(0, 0%, 95%); background-color: hsl(0, 0%, 45%); font-family: Arial, sans-serif; } `); let download_button; try { const Files = document.querySelectorAll("div.post__body h2") const spanElement = GM_addElement(Files[Files.length - 1], "span", {class: "File_Span"}); download_button = GM_addElement(spanElement, "button", { class: "Download_Button", }); if (CompressMode) { ModeDisplay = "壓縮下載"; } else { ModeDisplay = "單圖下載"; } download_button.textContent = ModeDisplay; download_button.addEventListener("click", function() { DownloadTrigger(download_button); }); } catch { download_button.textContent = "無法下載"; download_button.disabled = true; } } function IllegalFilter(Name) { return Name.replace(/[\/\?<>\\:\*\|":]/g, ''); } function Conversion(Name) { return Name.replace(/[\[\]]/g, ''); } async function DownloadTrigger(button) { let interval = setInterval(function() { let imgdata = document.querySelectorAll("a.fileThumb.image-link"); let title = document.querySelector("h1.post__title").textContent.trim(); let user = document.querySelector("a.post__user-name").textContent.trim(); if (imgdata && title && user) { button.textContent = "開始下載"; if (CompressMode) { ZipDownload(`[${user}] ${title}`, imgdata, button); } else { ImageDownload(`[${user}] ${title}`, imgdata, button) } clearInterval(interval); } }, 500); } async function ZipDownload(Folder, ImgData, Button) { const zip = new JSZip(), Data = Object.values(ImgData), File = Conversion(Folder), Total = Data.length, name = IllegalFilter(Folder.split(" ")[1]); let pool = [], poolSize = 5, progress = 1, mantissa; function createPromise(i) { return new Promise((resolve) => { GM_xmlhttpRequest({ method: "GET", url: Data[i].href.split("?f=")[0], responseType: "blob", onload: response => { if (response.status === 200 && response.response instanceof Blob && response.response.size > 0) { mantissa = progress.toString().padStart(3, '0'); zip.file(`${File}/${name}_${mantissa}.png`, response.response); Button.textContent = `下載進度 [${progress}/${Total}]`; progress++; } else { i--; } resolve(); } }); }); } for (let i = 0; i < Total; i++) { let promise = createPromise(i); pool.push(promise); if (pool.length >= poolSize) { await Promise.all(pool); pool = []; } } if (pool.length > 0) {await Promise.all(pool)} Compression(); function Compression() { Button.textContent = "壓縮封裝中[請稍後]"; zip.generateAsync({ type: "blob", compression: "DEFLATE", compressionOptions: { level: 5 // 壓縮級別,範圍從 0(無壓縮)到 9(最大壓縮) } }).then(zip => { Button.textContent = "下載完成"; saveAs(zip, `${Folder}.zip`); setTimeout(() => {Button.textContent = ModeDisplay}, 4000); }).catch( result => { Button.textContent = "壓縮封裝失敗"; setTimeout(() => {Button.textContent = ModeDisplay}, 6000); }); } } async function ImageDownload(Folder, ImgData, Button) { const name = IllegalFilter(Folder.split(" ")[1]), Data = Object.values(ImgData), Total = Data.length; let progress = 1; for (let i = 0; i < Total; i++) { GM_download({ url: Data[i].href.split("?f=")[0], name: `${name}_${(progress+i).toString().padStart(3, '0')}.png`, ontimeout: 5000, onload: () => { Button.textContent = `下載進度 [${progress}/${Total}]`; progress++; }, onerror: () => { i--; } }); } Button.textContent = "下載完成"; setTimeout(() => {Button.textContent = ModeDisplay}, 4000); } function OpenData() { try { let content = document.querySelector('.card-list__items').querySelectorAll('article.post-card'); content.forEach(function(content) { let link = content.querySelector('a').getAttribute('href'); setTimeout(() => { window.open("https://kemono.party" + link , "_blank"); }, 300); }); } catch { alert("這裡沒帖子給你開"); } }