// ==UserScript== // @name Lofter(乐乎)原图下载 修改版 // @namespace LofterSpiderFix // @license MIT // @version 1.0.2 // @author Kaesinol // @author 兰陵笑笑生 // @homepage https://gist.github.com/kaixinol/3652d2484de12818e9b402808db30801 // @description 批量下载Lofter图片,修改自 [Lofter原图查看下载](https://greasyfork.org/zh-CN/scripts/32942-lofter-%E4%B9%90%E4%B9%8E-%E5%8E%9F%E5%9B%BE%E6%9F%A5%E7%9C%8B%E4%B8%8B%E8%BD%BD) // @match https://*.lofter.com/post/* // @grant GM_xmlhttpRequest // @require https://update.greasyfork.icu/scripts/473358/1237031/JSZip.js // @downloadURL https://update.greasyfork.icu/scripts/524687/Lofter%28%E4%B9%90%E4%B9%8E%29%E5%8E%9F%E5%9B%BE%E4%B8%8B%E8%BD%BD%20%E4%BF%AE%E6%94%B9%E7%89%88.user.js // @updateURL https://update.greasyfork.icu/scripts/524687/Lofter%28%E4%B9%90%E4%B9%8E%29%E5%8E%9F%E5%9B%BE%E4%B8%8B%E8%BD%BD%20%E4%BF%AE%E6%94%B9%E7%89%88.meta.js // ==/UserScript== (function () { "use strict"; var css = document.createElement("style"); css.id = "spidercss"; var cssText = "#spiderboprt{position:fixed;top:7px;right:15px;margin:0 5px 0 0;z-index:9999999999999}#spiderboprt a,#spiderboprt em{height:23px;line-height:23px;float:left;background:url(//l.bst.126.net/rsc/img/control/operatenew24.png?005) no-repeat}#spiderboprt a{padding:0 2px 0 0;cursor:pointer;text-decoration:none;background-position:right 0}#spiderboprt a:hover em,#spiderboprt em{color:#fff;padding:0 5px 0 26px;white-space:nowrap;font-weight:400;font-style:normal}#spiderboprt em{background-position:0 -750px;font-size:12px}#spiderboprt a:hover{background-position:right -870px}#spiderboprt a:hover em{background-position:0 -780px}"; css.innerHTML = cssText; if (document.getElementById("spidercss") == undefined) { document.getElementsByTagName("head")[0].appendChild(css); } if (document.getElementById("spiderboprt") == undefined) { var Scope = document.getElementById("control_frame"); if (Scope) { Scope.style.right = "77px"; var boprt = document.createElement("div"); boprt.id = "spiderboprt"; Scope.parentNode.insertBefore(boprt, Scope.nextSibling); document.getElementById("spiderboprt").innerHTML = "下载"; } } var preg = /(.*?)\.(jpg|png|jpeg|gif)/i; function getAllImages() { var imgs = document.getElementsByClassName("imgclasstag"); var videos = document.getElementsByTagName("video"); return [ ...Array.from(imgs).map(function (img) { return img.getAttribute("bigimgsrc").match(preg)[0]; }), ...Array.from(videos).map(function (video) { return video.src; }), ]; } function getFileExtensionFromUrl(url) { // 移除查询参数(?后面的部分) const cleanUrl = url.split("?")[0]; // 提取文件后缀名 const match = cleanUrl.match(/\.([a-zA-Z0-9]+)$/); return match ? match[1] : ""; // 返回后缀名或空字符串 } function saveFile(blob, filename) { const url = URL.createObjectURL(blob); const link = document.createElement("a"); link.href = url; link.download = filename; document.body.appendChild(link); link.click(); document.body.removeChild(link); URL.revokeObjectURL(url); } function downloadImages(urls) { console.log(urls); if (urls.length === 0) return; const username = document.location.href.match( /https:\/\/(.+?)\.lofter\.com/ )[1]; const postId = document.location.href.match(/post\/(.+)/)[1]; if (urls.length > 2) { // 多于两张图片时打包下载 var jszip = new JSZip(); var promises = urls.map(function (url, index) { return new Promise(function (resolve) { GM_xmlhttpRequest({ method: "GET", url: url, responseType: "arraybuffer", headers: { "sec-fetch-site": "cross-site", referer: document.location.href, }, onload: function (xhr) { const fileExt = getFileExtensionFromUrl(url); jszip.file( `${username} - ${document.title} - ${postId}${ index + 1 }.${fileExt}`, xhr.response ); resolve(); }, }); }); }); Promise.all(promises).then(function () { jszip.generateAsync({ type: "blob" }).then(function (content) { saveFile(content, `${username} - ${postId}.zip`); }); }); } else { // 两张以下直接下载 urls.forEach(function (url) { const fileExt = getFileExtensionFromUrl(url); const filename = `${username} - ${document.title} - ${postId}.${fileExt}`; GM_xmlhttpRequest({ method: "GET", url: url, responseType: "blob", headers: { "sec-fetch-site": "cross-site", referer: document.location.href, }, onload: function (xhr) { saveFile(xhr.response, filename); }, }); }); } } // 添加点击事件处理 function addClickHandler() { var downloadBtn = document.getElementById("spiderboprt"); if (downloadBtn) { downloadBtn.onclick = function () { var imageUrls = getAllImages(); downloadImages(imageUrls); }; } } // 初始化 function init() { // 如果按钮不存在,尝试创建 if (!document.getElementById("spiderboprt")) { var controlFrame = document.getElementById("control_frame"); if (controlFrame) { controlFrame.style.right = "77px"; var boprt = document.createElement("div"); boprt.id = "spiderboprt"; controlFrame.parentNode.insertBefore(boprt, controlFrame.nextSibling); boprt.innerHTML = "下载"; } } // 添加点击事件 addClickHandler(); } // 页面加载完成后初始化 if (document.readyState === "loading") { document.addEventListener("DOMContentLoaded", init); } else { init(); } })();