.:. 草榴社區 » 技術討論區 » [技术贴]原油猴脚本“CL社区收藏夹”修正版,期待技术大佬继续优化
本頁主題: [技术贴]原油猴脚本“CL社区收藏夹”修正版,期待技术大佬继续优化字體大小 寬屏顯示 只看樓主 最新點評 熱門評論 時間順序
总加速师


級別:騎士 ( 10 )
發帖:1583
威望:181 點
金錢:613 USD
貢獻:9000 點
註冊:2020-06-23

[技术贴]原油猴脚本“CL社区收藏夹”修正版,期待技术大佬继续优化

很久前社区某个大佬开发过一个脚本“CL社区收藏夹”,非常喜欢,后来停更了,插件失效。因本人不懂技术,无力,甚是想念该插件。昨日用gpt优化尝试,没想到可用,主要优化了图片下载,甚是喜爱这功能。
借此,再次呼唤原开发大佬,期待您的继续更新优化,原帖地址如下:https://openuserjs.org/scripts/zhangsan/CL%E7%A4%BE%E5%8C%BA%E6%94%B6%E8%97%8F%E5%A4%B9

顺便发个码,夹子绕行,新手请熟读版规,得码者跟帖回复下,否则举报取消。
c212*75*90*4a3a7     05-21 13:57
“*”隐藏3个相同字母,字母范围,前10

具体操作,将代码复制,打开油猴,点击 已安装脚本,随便一个脚本点击 操作下的 编辑,删除现有代码,把复制的代码粘贴到编辑器中,点击编辑器左上角保存,生成新的脚本,即可正常使用。
目前谷歌测试良好,
代码如下:

// ==UserScript==
// @name        CL社区收藏夹 最终增强稳定版
// @namespace    http://tampermonkey.net/
// @version      3.8
// @description  收藏 + 导入导出 + 仅下载1楼图片 + 顺序下载 + 正确楼主ID + 版块名命名
// @author      niuhe + ChatGPT
// @match        http*://*/htm_data/*
// @match        http*://*/htm_mob/*
// @match        http*://*/profile.php?action=favor
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_listValues
// @grant        GM_setClipboard
// @grant        GM_download
// @grant        GM_deleteValue
// ==/UserScript==

(function () {

    'use strict';

    const url = location.href;

    const isCollectionPage =
        url.includes("profile.php?action=favor");

    // =====================================
    // 工具
    // =====================================

    function $(selector) {

        return document.querySelector(selector);
    }

    function safeName(str) {

        return str
            .replace(/[\\/:*?"<>|]/g, "_")
            .replace(/\s+/g, " ")
            .trim();
    }

    function getText(selector, fallback = "") {

        const el = $(selector);

        return el
            ? el.textContent.trim()
            : fallback;
    }

    function genKey(url) {

        try {

            return new URL(url).pathname;

        } catch {

            return url;
        }
    }

    function getTagContainer() {

        return $(".tiptop")
            || $(".guide")
            || $("h3")
            || document.body;
    }

    function addSeparator() {

        const span =
            document.createElement("span");

        span.innerText = " | ";

        getTagContainer()
            .appendChild(span);
    }

    function createBtn(
        text,
        color = "#2F5FA1"
    ) {

        const a =
            document.createElement("a");

        a.href = "javascript:void(0)";

        a.innerText = text;

        a.style.margin = "0 5px";
        a.style.color = color;
        a.style.cursor = "pointer";
        a.style.fontWeight = "bold";

        return a;
    }

    // =====================================
    // 获取标题
    // =====================================

    function getTitle() {

        let title =

            getText("h4")
            || getText(".f18")
            || document.title;

        title = title
            .replace(" [复制链接]", "")
            .trim();

        return safeName(title);
    }

    // =====================================
    // 获取楼主ID
    // =====================================

    function getAuthor() {

        try {

            const node =
                document.querySelector("th b");

            if (
                node &&
                node.textContent.trim()
            ) {

                const username =
                    node.textContent.trim();

                console.log(
                    "成功读取楼主:",
                    username
                );

                return safeName(username);
            }

        } catch (err) {

            console.log(
                "读取楼主失败:",
                err
            );
        }

        return "未知用户";
    }

    // =====================================
    // 获取版块名称
    // =====================================

    function getForumName() {

        try {

            const links =
                document.querySelectorAll('a[href*="thread"]');

            for (const node of links) {

                const text =
                    node.textContent.trim();

                if (
                    text &&
                    text.length < 30 &&
                    !text.includes("版規") &&
                    !text.includes("返回")
                ) {

                    console.log(
                        "成功读取版块:",
                        text
                    );

                    return safeName(text);
                }
            }

        } catch (err) {

            console.log(
                "读取版块失败:",
                err
            );
        }

        return "未知版块";
    }

    const title = getTitle();

    const author = getAuthor();

    const forumName = getForumName();

    // =====================================
    // 收藏数据
    // =====================================

    const saveUrl = url
        .replace(location.host, "**")
        .replace("htm_data", "htm_mob");

    const key = genKey(saveUrl);

    const content = JSON.stringify({

        title,
        author,
        forumName,
        url: saveUrl,
        time: Date.now()

    });

    // =====================================
    // 收藏按钮
    // =====================================

    function addFavoriteBtn() {

        addSeparator();

        const saved =
            GM_getValue(key);

        const btn = createBtn(

            saved
                ? "已收藏"
                : "收藏",

            saved
                ? "#ff0000"
                : "#2F5FA1"
        );

        btn.addEventListener("click", () => {

            if (GM_getValue(key)) {

                GM_deleteValue(key);

                btn.innerText = "收藏";

                btn.style.color = "#2F5FA1";

            } else {

                GM_setValue(key, content);

                btn.innerText = "已收藏";

                btn.style.color = "#ff0000";
            }
        });

        getTagContainer()
            .appendChild(btn);
    }

    // =====================================
    // 导出
    // =====================================

    function exportCollection() {

        addSeparator();

        const btn =
            createBtn("导出");

        btn.addEventListener("click", () => {

            const keys =
                GM_listValues();

            const data = [];

            keys.forEach(k => {

                data.push(
                    GM_getValue(k)
                );
            });

            const blob = new Blob(

                [data.join("\n")],

                {
                    type: "text/plain"
                }
            );

            const link =
                document.createElement("a");

            link.href =
                URL.createObjectURL(blob);

            link.download =
                "favorite.dat";

            link.click();

            alert("导出成功");
        });

        getTagContainer()
            .appendChild(btn);
    }

    // =====================================
    // 导入
    // =====================================

    function importCollection() {

        addSeparator();

        const input =
            document.createElement("input");

        input.type = "file";

        input.accept = ".dat";

        input.style.width = "90px";

        input.addEventListener("change", e => {

            const file =
                e.target.files[0];

            if (!file) return;

            const reader =
                new FileReader();

            reader.onload = () => {

                const arr =
                    reader.result.split("\n");

                arr.forEach(line => {

                    if (!line.trim()) return;

                    try {

                        const obj =
                            JSON.parse(line);

                        GM_setValue(

                            genKey(obj.url),

                            line
                        );

                    } catch {}
                });

                alert("导入成功");
            };

            reader.readAsText(file);
        });

        getTagContainer()
            .appendChild(input);
    }

    // =====================================
    // 下载图片(顺序下载)
    // =====================================

    async function downloadImages() {

        addSeparator();

        const btn =
            createBtn("下载图片");

        btn.addEventListener("click", async () => {

            let firstFloor =

                document.querySelector(".tpc_content")
                || document.querySelector(".tpc_cont");

            if (!firstFloor) {

                alert("未找到1楼正文");

                return;
            }

            const imgList =
                firstFloor.querySelectorAll("img");

            let images = [];

            imgList.forEach(img => {

                let src =

                    img.getAttribute("ess-data")
                    || img.getAttribute("data-src")
                    || img.src;

                if (!src) return;

                // 排除头像/LOGO/GIF
                if (

                    src.includes("face")
                    || src.includes("avatar")
                    || src.includes("logo")
                    || src.includes("icon")
                    || src.includes(".gif")

                ) {

                    return;
                }

                // 仅图片
                if (
                    /\.(jpg|jpeg|png|webp)$/i
                    .test(src)
                ) {

                    images.push(src);
                }
            });

            // 去重
            images =
                [...new Set(images)];

            if (images.length === 0) {

                alert("未找到图片");

                return;
            }

            // 复制链接
            GM_setClipboard(
                images.join("\n")
            );

            // 文件夹名
            const folderName =
                `${author}_${forumName}_${title}`;

            const ok = confirm(

                `检测到 ${images.length} 张图片\n\n`
                + `保存目录:${folderName}\n\n`
                + `是否开始下载?`
            );

            if (!ok) return;

            let i = 1;

            // 顺序下载
            for (const img of images) {

                let ext = "jpg";

                try {

                    ext = new URL(img)
                        .pathname
                        .split(".")
                        .pop();

                } catch {}

                const filename =
                    `${folderName}/${i}.${ext}`;

                console.log(
                    "开始下载:",
                    filename
                );

                // 等待当前图片完成
                await new Promise(resolve => {

                    GM_download({

                        url: img,

                        name: filename,

                        saveAs: false,

                        timeout: 60000,

                        onload: () => {

                            console.log(
                                "下载完成:",
                                filename
                            );

                            resolve();
                        },

                        onerror: (e) => {

                            console.log(
                                "下载失败:",
                                filename,
                                e
                            );

                            resolve();
                        },

                        ontimeout: () => {

                            console.log(
                                "下载超时:",
                                filename
                            );

                            resolve();
                        }
                    });
                });

                i++;

                // 下载间隔
                await new Promise(r =>
                    setTimeout(r, 1000)
                );
            }

            alert("全部下载任务完成");
        });

        getTagContainer()
            .appendChild(btn);
    }

    // =====================================
    // 收藏页
    // =====================================

    function showCollectionPage() {

        const keys =
            GM_listValues();

        const list = [];

        keys.forEach(k => {

            try {

                const obj =
                    JSON.parse(
                        GM_getValue(k)
                    );

                list.push(obj);

            } catch {}
        });

        list.sort((a, b) =>
            b.time - a.time
        );

        const html = list.map((item, index) => {

            const realUrl = item.url
                .replace("**", location.host)
                .replace("htm_mob", "htm_data");

            return `

            <div style="
                padding:12px;
                border-bottom:1px solid #ddd;
            ">

                <a href="${realUrl}"
                  target="_blank"
                  style="
                    font-size:16px;
                    color:#2F5FA1;
                    font-weight:bold;
                  ">

                  ${index + 1}. ${item.title}

                </a>

                <div style="
                    color:#666;
                    margin-top:6px;
                    font-size:13px;
                ">

                    ${item.author}

                </div>

            </div>
            `;

        }).join("");

        document.body.innerHTML = `

        <div style="
            max-width:900px;
            margin:auto;
            background:#fff;
        ">

            <h2 style="
                padding:15px;
            ">
                本地收藏夹 (${list.length})
            </h2>

            ${html}

        </div>
        `;
    }

    // =====================================
    // 主逻辑
    // =====================================

    if (!isCollectionPage) {

        addFavoriteBtn();

        exportCollection();

        importCollection();

        downloadImages();

    } else {

        showCollectionPage();
    }

    console.log(
        "CL社区收藏夹最终增强稳定版加载成功"
    );

})();

赞(59)
DMCA / ABUSE REPORT | TOP Posted: 05-21 15:39 發表評論
.:. 草榴社區 » 技術討論區

電腦版 手機版 客戶端 DMCA
用時 0.01(s) x3, 06-05 09:54