您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Download images or text from Poipiku
当前为
// ==UserScript== // @name Poipiku Downloader // @name:zh-CN Poipiku下载器 // @description Download images or text from Poipiku // @description:zh-cn 从Poipiku下载图片或文字 // @author calary // @namespace http://tampermonkey.net/ // @version 0.3.2 // @license GPL-3.0 // @include http*://poipiku.com* // @match https://poipiku.com/ // @connect img.poipiku.com // @connect img-org.poipiku.com // @icon https://poipiku.com/favicon.ico // @require https://cdn.bootcdn.net/ajax/libs/jquery/2.2.4/jquery.min.js // @require https://cdn.bootcss.com/jszip/3.1.4/jszip.min.js // @require https://cdn.bootcss.com/FileSaver.js/1.3.2/FileSaver.min.js // @grant GM.xmlHttpRequest // @grant GM_xmlhttpRequest // @run-at document-end // ==/UserScript== jQuery(function ($) { const lang = ( window.navigator.language || window.navigator.browserLanguage || "en-us" ).toLowerCase(); const i18nMap = { "en-us": { ui_logined: "Logined", ui_password: "Password", ui_qualitytrue: "You can download high quality images.", ui_qualityfalse: "You cannot download high quality images.", ui_mode: "Rename image with page id", btn_downloadimages: "Save images (.zip)", btn_downloadimageseperately: "Save images Seperately", btn_downloadtext: "Save text (.txt)", error_default: "Something went wrong", error_fetch: "Fetch content error. Entered wrong password?", error_noimage: "No Images", txt_title: "Title: ", txt_author: "Author: ", txt_twitter: "Twitter: ", txt_link: "Link: ", }, "zh-cn": { ui_logined: "登录(不可用)状态", ui_password: "密码", ui_qualitytrue: "可以下载高质量图片。", ui_qualityfalse: "不能下载高质量图片。", ui_mode: "图片命名包含当页ID", btn_downloadimages: "图片打包为(.zip)", btn_downloadimageseperately: "独立保存图片", btn_downloadtext: "保存文字为(.txt)", error_default: "出错了", error_fetch: "请求失败。是否输入密码有误?", error_noimage: "没有图片", txt_title: "标题:", txt_author: "作者:", txt_twitter: "推特:", txt_link: "地址:", }, }; const i18n = (key) => (i18nMap[lang] && i18nMap[lang][key]) || i18nMap["en-us"][key]; const website = "poipiku"; const url = window.location.href; const execResult = /\/(\d+)\/(\d+)/.exec(url); const authorId = execResult && execResult[1]; const workId = execResult && execResult[2]; const logined = $(".LoginButton").length === 0; const isText = $(".IllustItem").hasClass("Text"); const hasPassword = $(".IllustItem").hasClass("Password"); const fontFamily = "Arial, 'Microsoft Yahei', Helvetica, sans-serif"; if (!workId) { return; } const $panel = $(`<div> <div>${i18n("ui_logined")}: <b style="color:red">${logined}</b>.</div> <div class="line-qualitytip" >${ logined ? i18n("ui_qualitytrue") : i18n("ui_qualityfalse") }</div> <div class="line-password">${i18n( "ui_password" )} <input type='text' class="password"></div> <div class="line-mode" >${i18n( "ui_mode" )} <input type='checkbox' class="saveFileMode"></div> <div class="line-images"> <button class="btn-downloadImagesSeperately" style="font-size:20px">${i18n( "btn_downloadimageseperately" )} <b class='status'></b></button></button><br> <button class="btn-downloadImages" style="font-size:20px">${i18n( "btn_downloadimages" )} <b class='status'></b></button> </div> <div class="line-text"><button class="btn-downloadText" style="font-size:20px">${i18n( "btn_downloadtext" )}</button></div> </div>`) .css({ position: "fixed", left: 0, top: 50, zIndex: 999999, background: "#fff", color: "#333", fontSize: 18, fontFamily: fontFamily, padding: 10, }) .appendTo($("body")); const $password = $panel.find(".password"); const $saveFileMode = $panel.find(".saveFileMode"); $panel.find("button").css({ fontFamily: fontFamily, }); if (!hasPassword) { $panel.find(".line-password").hide(); } if (isText) { $panel.find(".line-images").hide(); $panel.find(".line-qualitytip").hide(); $panel.find(".line-mode").hide(); } else { $panel.find(".line-text").hide(); } $panel.find(".btn-downloadImages").on("click", downloadImagesAsZip); $panel .find(".btn-downloadImagesSeperately") .on("click", downloadImagesSeperately); $panel.find(".btn-downloadText").on("click", downloadText); function request(config) { return new Promise((resolve, reject) => { $.ajax({ ...config, success: (response) => { resolve(response); }, error: () => { reject(new Error(i18n("error_default"))); }, }); }); } function getBlob(url) { // return fetch(url).then((response) => response.blob()); return new Promise((resolve, reject) => { GM.xmlHttpRequest({ method: "GET", url: url, responseType: "blob", headers: { referer: window.location.href }, onload: (payload) => { resolve(payload.response); }, onerror: () => { reject(new Error(i18n("error_default"))); }, }); }); } // 过滤文件名非法字符 function filterFilename(filename) { return filename.replace(/\?|\*|\:|\"|\<|\>|\\|\/|\|/g, ""); } // 生成保存文件名 function getSaveFilename() { const twitter = $(".UserInfoProgile a").html(); const username = $(".UserInfoUserName a").html(); const username2 = twitter ? twitter.substring(1) : username; const desc = $(".IllustItemDesc").text().substring(0, 20); return filterFilename( `[${username2}][${website}][${authorId}_${workId}]${desc}` ); } // 生成保存图片文件名 // 默认:序号.后缀名 // 选中:网站_作品id_序号.后缀名 function getSaveImageFilename(src, index) { let suffix = src.split(".").splice(-1); const mode = $saveFileMode.is(":checked"); if (mode) { return `${website}_${workId}_${index + 1}.${suffix}`; } return `${index + 1}.${suffix}`; } // 批量下载图片的默认方法 function saveImages(list, saveAsZip, $status) { let zip = new JSZip(); let finishehCount = 0; let folder = zip.folder(getSaveFilename()); $status = $status || $("<div></div>"); $status.text(`0/${list.length}`); let promises = list.map((src, index) => { return getBlob(src).then((blob) => { finishehCount++; $status.text(`${finishehCount}/${list.length}`); if (saveAsZip) { folder.file(getSaveImageFilename(src, index), blob, { binary: true }); } else { let suffix = src.split(".").splice(-1); saveAs( new Blob([blob]), `${getSaveFilename()}_${index + 1}.${suffix}` ); console.log("save image", index); } }); }); Promise.all(promises).then(() => { if (saveAsZip) { zip .generateAsync({ type: "blob", base64: true }) .then((content) => saveAs(content, getSaveFilename())); } }); } // 保存文字的默认方法 function saveText(option) { let str = ""; if (option.title) { str += `${i18n("txt_title")}${option.title}\n`; } if (option.author) { str += `${i18n("txt_author")}${option.author}\n`; } if (option.twitter) { str += `${i18n("txt_twitter")}${option.twitter}\n`; } str += `${i18n("txt_link")}${window.location.href}\n`; str += `\n\n`; str += option.content; saveAs( new Blob([str], { type: "text/plain;charset=UTF-8" }), getSaveFilename() + ".txt" ); } // 下载图片 function downloadImages(saveAsZip, $status) { const promise = logined ? request({ url: "/f/ShowIllustDetailF.jsp", type: "POST", data: { ID: authorId, TD: workId, AD: "-1", PAS: $password.val(), }, dataType: "json", }).then((payload) => { if (!payload.html) { throw new Error(i18n("error_fetch")); } return payload.html; }) : request({ url: "/f/ShowAppendFileF.jsp", type: "POST", data: { UID: authorId, IID: workId, PAS: $password.val(), MD: 0, TWF: -1, }, dataType: "json", }).then((payload) => { if (payload.result_num < 0) { throw new Error(payload.html); } return $(".IllustItemThumb").eq(0).prop("outerHTML") + payload.html; }); promise .then((html) => { let $page = $(html); let list = []; $page .find(logined ? ".DetailIllustItemImage" : ".IllustItemThumbImg") .each(function () { const src = $(this).attr("src"); if (src && !/warning\.png/.test(src)) { list.push(window.location.protocol + src); } }); if (list.length) { saveImages(list, saveAsZip, $status); } else { throw new Error(i18n("error_noimage")); } }) .catch((e) => { alert(e.message || i18n("error_default")); }); } // 打包图片 function downloadImagesAsZip() { downloadImages(true, $(this).find(".status")); } // 独立下载图片 function downloadImagesSeperately() { downloadImages(false, $(this).find(".status")); } // 下载文字 function downloadText() { request({ url: "/f/ShowAppendFileF.jsp", type: "POST", data: { UID: authorId, IID: workId, PAS: $password.val(), MD: 0, TWF: -1, }, dataType: "json", }) .then((payload) => { if (payload.result_num < 0) { throw new Error(payload.html); } let $page = $(payload.html); saveText({ title: $(".IllustItemDesc").text(), author: $(".UserInfoUserName a").html(), twitter: $(".UserInfoProgile a").prop("href"), content: $page.find(".NovelSection").text(), }); }) .catch((e) => { alert(e.message || i18n("error_default")); }); } });
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址