Greasy Fork

Greasy Fork is available in English.

🔥🔥嗅探网站图片,一键下载(支持贴吧,豆瓣)🔥🔥

嗅探网站的图片,支持一键下载里面的图片,包括360图书馆,百度贴吧,豆瓣高清图片批量下载,后续再增加图源

目前为 2024-02-21 提交的版本,查看 最新版本

// ==UserScript==
// @name         🔥🔥嗅探网站图片,一键下载(支持贴吧,豆瓣)🔥🔥
// @namespace    https://www.softrr.cn/
// @version      1.1.1
// @author       hackhase
// @description  嗅探网站的图片,支持一键下载里面的图片,包括360图书馆,百度贴吧,豆瓣高清图片批量下载,后续再增加图源
// @license      MIT
// @icon         http://pubimage.360doc.com/index7/nlogo.jpg
// @match        *://www.360doc.com/content/*
// @match        *://tieba.baidu.com/*
// @match        *://*.douban.com/photos/*
// @match        *://movie.douban.com/subject/*
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.global.prod.js
// @require      data:application/javascript,%3Bwindow.Vue%3DVue%3B
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/index.full.min.js
// @resource     element-plus/dist/index.css  https://cdn.jsdelivr.net/npm/[email protected]/dist/index.css
// @connect      www.softrr.cn
// @connect      tieba.baidu.com
// @connect      tiebapic.baidu.com
// @connect      tb2.bdstatic.com
// @connect      *
// @connect      www.douban.com
// @connect      movie.douban.com
// @grant        GM_addStyle
// @grant        GM_getResourceText
// @grant        GM_xmlhttpRequest
// @grant        unsafeWindow
// @noframes
// ==/UserScript==

(t=>{if(typeof GM_addStyle=="function"){GM_addStyle(t);return}const e=document.createElement("style");e.textContent=t,document.head.append(e)})(" :root{font-family:Inter,Avenir,Helvetica,Arial,sans-serif;font-size:16px;line-height:24px;font-weight:400;color-scheme:light dark;color:#ffffffde;background-color:#242424;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-text-size-adjust:100%}a{font-weight:500;color:#646cff;text-decoration:inherit}a:hover{color:#535bf2}body{margin:0;place-items:center;min-width:320px;min-height:100vh}h1{font-size:3.2em;line-height:1.1}button{border-radius:8px;border:1px solid transparent;padding:.6em 1.2em;font-size:1em;font-weight:500;font-family:inherit;background-color:#1a1a1a;cursor:pointer;transition:border-color .25s}button:hover{border-color:#646cff}button:focus,button:focus-visible{outline:4px auto -webkit-focus-ring-color}.card{padding:2em}@media (prefers-color-scheme: light){:root{color:#213547;background-color:#fff}a:hover{color:#747bff}button{background-color:#f9f9f9}}.modal-wrapper[data-v-eb552d62]{position:fixed;top:0;left:0;width:100%;height:100%;background-color:#00000080;margin-top:0;display:flex;justify-content:center;align-items:center;z-index:999}.modal[data-v-eb552d62]{background-color:#fff;padding:20px;border-radius:5px}.header[data-v-eb552d62]{display:flex;justify-content:space-between;align-items:center;margin-bottom:10px}.header h2[data-v-eb552d62]{margin:0;font-size:20px;font-weight:700}.header button[data-v-eb552d62]{border:none;background-color:transparent;font-size:20px;cursor:pointer}.content[data-v-eb552d62]{max-height:400px;overflow:auto;font-size:16px;display:flex;justify-content:space-between}.content .produce[data-v-eb552d62]{flex:60%}.content .produce p[data-v-eb552d62]{margin-top:15px}.content .produce .ipt[data-v-eb552d62]{margin-top:15px;height:30px;border-radius:5px;padding-left:10px}.content .img[data-v-eb552d62]{flex:35%;height:180px;display:flex;align-items:center;justify-content:center}.content .img img[data-v-eb552d62]{width:180px}input[data-v-eb552d62]::-webkit-input-placeholder{color:#aab2bd;font-size:14px;padding-left:5px}.copy[data-v-a5b45cdd]{width:200px;position:fixed;right:10px;top:80px}.copy .down[data-v-a5b45cdd]{display:flex;align-items:center;justify-content:center;flex-wrap:wrap;width:80px;height:80px;border-radius:50%;font-size:14px;color:#fff;background-color:red!important;cursor:pointer}.copy .down[data-v-a5b45cdd]:hover{background-color:#00ff48!important} ");

(async function (vue, elementPlus) {
  'use strict';

  var _GM_xmlhttpRequest = /* @__PURE__ */ (() => typeof GM_xmlhttpRequest != "undefined" ? GM_xmlhttpRequest : void 0)();
  var _unsafeWindow = /* @__PURE__ */ (() => typeof unsafeWindow != "undefined" ? unsafeWindow : void 0)();
  const _export_sfc = (sfc, props) => {
    const target = sfc.__vccOpts || sfc;
    for (const [key, val] of props) {
      target[key] = val;
    }
    return target;
  };
  const _withScopeId$1 = (n) => (vue.pushScopeId("data-v-eb552d62"), n = n(), vue.popScopeId(), n);
  const _hoisted_1$1 = { class: "modal" };
  const _hoisted_2$1 = { class: "header" };
  const _hoisted_3 = { class: "content" };
  const _hoisted_4 = { class: "produce" };
  const _hoisted_5 = /* @__PURE__ */ _withScopeId$1(() => /* @__PURE__ */ vue.createElementVNode("p", null, "1、扫描右侧公众号,点击关注!", -1));
  const _hoisted_6 = /* @__PURE__ */ _withScopeId$1(() => /* @__PURE__ */ vue.createElementVNode("p", null, "2、在软件爬取者后台回复:验证码", -1));
  const _hoisted_7 = /* @__PURE__ */ _withScopeId$1(() => /* @__PURE__ */ vue.createElementVNode("p", null, "3、在下方输入框输入获取的验证码后回车", -1));
  const _hoisted_8 = /* @__PURE__ */ _withScopeId$1(() => /* @__PURE__ */ vue.createElementVNode("div", { class: "img" }, [
    /* @__PURE__ */ vue.createElementVNode("img", {
      src: "https://www.softrr.cn/assets/pqz-daa4b840.jpg",
      alt: ""
    })
  ], -1));
  const _sfc_main$1 = {
    __name: "Model",
    props: {
      title: {
        type: String,
        required: true
      },
      code: {
        type: Number
      }
    },
    setup(__props, { expose: __expose }) {
      const props = __props;
      const visible = vue.ref(false);
      const openModal = () => {
        visible.value = true;
      };
      const closeModal = () => {
        visible.value = false;
      };
      __expose({
        visible,
        openModal,
        closeModal
      });
      const codeValue = vue.ref();
      const enterCode = () => {
        if (codeValue.value == props.code) {
          localStorage.setItem("code", codeValue.value);
          visible.value = false;
          alert("验证成功,请再次点击解析!");
          codeValue.value = "";
        } else {
          alert("验证码错误,请重新输入!");
          codeValue.value = "";
        }
      };
      return (_ctx, _cache) => {
        return vue.withDirectives((vue.openBlock(), vue.createElementBlock("div", {
          class: "modal-wrapper",
          onClick: vue.withModifiers(closeModal, ["self"])
        }, [
          vue.createElementVNode("div", _hoisted_1$1, [
            vue.createElementVNode("div", _hoisted_2$1, [
              vue.createElementVNode("h2", null, vue.toDisplayString(__props.title), 1),
              vue.createElementVNode("button", { onClick: closeModal }, "X")
            ]),
            vue.createElementVNode("div", _hoisted_3, [
              vue.createElementVNode("div", _hoisted_4, [
                _hoisted_5,
                _hoisted_6,
                _hoisted_7,
                vue.withDirectives(vue.createElementVNode("input", {
                  class: "ipt",
                  type: "text",
                  "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => codeValue.value = $event),
                  onKeydown: vue.withKeys(enterCode, ["enter"]),
                  placeholder: "请输入验证码后按回车"
                }, null, 544), [
                  [vue.vModelText, codeValue.value]
                ])
              ]),
              _hoisted_8
            ])
          ])
        ], 512)), [
          [vue.vShow, visible.value]
        ]);
      };
    }
  };
  const Model = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-eb552d62"]]);
  const importScript = (src) => {
    return new Promise((resolve, reject) => {
      const script = document.createElement("script");
      script.src = src;
      script.addEventListener("load", () => {
        var _a;
        resolve();
        (_a = script.parentElement) == null ? void 0 : _a.removeChild(script);
      });
      script.addEventListener("error", (e) => {
        var _a;
        reject(e);
        (_a = script.parentElement) == null ? void 0 : _a.removeChild(script);
      });
      document.body.appendChild(script);
    });
  };
  await( importScript(
    "https://cdn.jsdelivr.net/npm/[email protected]/dist/jszip.min.js"
  ));
  const JSZip = _unsafeWindow == null ? void 0 : _unsafeWindow.JSZip;
  const getFile = (url) => {
    return new Promise((resolve, reject) => {
      _GM_xmlhttpRequest({
        method: "GET",
        url,
        headers: {
          "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.289 Safari/537.36"
        },
        responseType: "blob",
        onload: function(res) {
          resolve(res.response);
        }
      });
    });
  };
  const getFileDoc = (url) => {
    return new Promise((resolve, reject) => {
      let xmlhttp = new XMLHttpRequest();
      xmlhttp.open("GET", url, true);
      xmlhttp.responseType = "blob";
      xmlhttp.onload = function() {
        if (this.status == 200) {
          resolve(this.response);
        } else {
          reject(this.status);
        }
      };
      xmlhttp.send();
    });
  };
  const downFile = async (arrList) => {
    const zip = new JSZip();
    const promises = [];
    await arrList.forEach((item) => {
      if (item.src.includes("360doc")) {
        const promise = getFileDoc(item.src).then((data) => {
          const lst = item.src.split(".");
          const fileType = lst[lst.length - 1].includes("?") ? lst[lst.length - 1].split("?")[0] : lst[lst.length - 1];
          zip.file(Date.now() + "." + fileType, data, { binary: true });
        });
        promises.push(promise);
      } else if (item.src.includes("tieba")) {
        const promise = getFile(item.src).then((data) => {
          const lst = item.src.split(".");
          const fileType = lst[lst.length - 1].includes("?") ? lst[lst.length - 1].split("?")[0] : lst[lst.length - 1];
          zip.file(Date.now() + "." + fileType, data, { binary: true });
        });
        promises.push(promise);
      } else if (item.src.includes("douban")) {
        if (item.src.includes("photo/m")) {
          item.src = item.src.replace("photo/m", "photo/l");
        }
        if (item.src.includes("photo/sqxs")) {
          item.src = item.src.replace("photo/sqxs", "photo/l");
        }
        const promise = getFile(item.src).then((data) => {
          const lst = item.src.split(".");
          const fileType = lst[lst.length - 1];
          zip.file(Date.now() + "." + fileType, data, { binary: true });
        });
        promises.push(promise);
      }
    });
    Promise.all(promises).then(() => {
      zip.generateAsync({ type: "blob" }).then((content) => {
        downLoad(content, "图片下载", "zip");
      });
    });
  };
  const downLoad = (blob, name, type) => {
    if (!blob || !type)
      return;
    const url = window.URL || window.webkitURL || window.moxURL;
    const downloadHref = url.createObjectURL(blob);
    const link = document.createElement("a");
    link.href = downloadHref;
    link.download = `${name || "导出文件"}.${type}`;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    url.revokeObjectURL(downloadHref);
  };
  const _withScopeId = (n) => (vue.pushScopeId("data-v-a5b45cdd"), n = n(), vue.popScopeId(), n);
  const _hoisted_1 = {
    class: "copy",
    ref: "btnGroupRef"
  };
  const _hoisted_2 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("br", null, null, -1));
  const _sfc_main = {
    __name: "App",
    setup(__props) {
      const imgList = vue.ref([]);
      let url = window.location.href;
      const getImageList = () => {
        if (url.includes("360doc")) {
          var a_left = document.querySelector(".a_left");
          a_left.style.zIndex = 0;
          imgList.value = document.querySelector("#artContent").querySelectorAll("img");
        }
        if (url.includes("tieba")) {
          var card_head = document.querySelector(".head_main") || document.querySelector("#container");
          card_head.style.zIndex = 0;
          imgList.value = document.querySelector("#pb_content").querySelectorAll("img");
        }
        if (url.includes("douban")) {
          if (url.includes("photos/album")) {
            console.log(1);
            imgList.value = document.querySelector(".photolst").querySelectorAll("img");
          }
          if (url.includes("subject")) {
            imgList.value = document.querySelector(".article").querySelectorAll("img");
          }
        }
      };
      const code = vue.ref();
      const getCode = () => {
        return new Promise((resolve, reject) => {
          _GM_xmlhttpRequest({
            method: "GET",
            url: `https://www.softrr.cn/crawler/getCode`,
            headers: {
              Referer: "https://www.softrr.cn/",
              "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.289 Safari/537.36"
            },
            onload: function(res) {
              code.value = JSON.parse(res.response).data[0].code;
              resolve(code.value);
            }
          });
        });
      };
      const title = vue.ref("为了减少端口压力,防止滥用,采取必要的验证手段。");
      const model = vue.ref("");
      const locoCode = vue.ref();
      const onImage = async () => {
        locoCode.value = localStorage.getItem("code");
        code.value = await getCode();
        if (locoCode.value == code.value) {
          downLoad2();
        } else {
          model.value.openModal();
        }
      };
      const downLoad2 = () => {
        let list = [];
        getImageList();
        imgList.value.forEach((item) => {
          if (item.src.includes("default"))
            return;
          if (url.includes("tieba") && !item.src.includes("gss0")) {
            if (item.src.includes("?")) {
              list.push(item);
            }
          }
          if (url.includes("360doc")) {
            list.push(item);
          }
          if (url.includes("douban")) {
            list.push(item);
          }
        });
        if (list.length === 0) {
          elementPlus.ElMessage({
            type: "info",
            message: "请至少选择一个文件下载"
          });
          return;
        }
        downFile(list);
      };
      return (_ctx, _cache) => {
        return vue.openBlock(), vue.createElementBlock("div", _hoisted_1, [
          vue.createElementVNode("a", {
            onClick: onImage,
            class: "down"
          }, [
            vue.createTextVNode("图片"),
            _hoisted_2,
            vue.createTextVNode("下载")
          ]),
          vue.createVNode(Model, {
            title: title.value,
            code: code.value,
            ref_key: "model",
            ref: model
          }, null, 8, ["title", "code"])
        ], 512);
      };
    }
  };
  const App = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-a5b45cdd"]]);
  const cssLoader = (e) => {
    const t = GM_getResourceText(e);
    return GM_addStyle(t), t;
  };
  cssLoader("element-plus/dist/index.css");
  vue.createApp(App).mount(
    (() => {
      const app = document.createElement("div");
      document.body.append(app);
      return app;
    })()
  );

})(Vue, ElementPlus);