Greasy Fork

Lofter(乐乎)原图下载 修改版

批量下载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)

// ==UserScript==
// @name         Lofter(乐乎)原图下载 修改版
// @namespace    LofterSpiderFix
// @license      MIT
// @version      1.0.2
// @author       Kaesinol, 兰陵笑笑生
// @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.org/scripts/473358/1237031/JSZip.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 = "<a><em>下载</em></a>";
    }
  }
 
  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 = "<a><em>下载</em></a>";
      }
    }
 
    // 添加点击事件
    addClickHandler();
  }
 
  // 页面加载完成后初始化
  if (document.readyState === "loading") {
    document.addEventListener("DOMContentLoaded", init);
  } else {
    init();
  }
})();