微博视频保存

支持微博视频、图片保存

// ==UserScript==
// @name         微博视频保存
// @namespace    https://yffjglcms.com/
// @version      20241007
// @description  支持微博视频、图片保存
// @author       yffjglcms
// @match        *://s.weibo.com/*
// @icon         data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant        none
// @require      https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/jszip/3.7.1/jszip.min.js
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    // Your code here...
    // card-act
    // thumbnail

    // 如果存在则执行
    function ifExist(selector, func, timeout){
        console.log('check ifExist ...' + selector)
        if(!timeout){
            timeout = 5000
        }

        if(document.querySelector(selector)==null)
        {
            setTimeout( function(){ifExist(selector, func);}, timeout);
        }
        else
        {
            func()
        }
    }

    function closest(selector, element) {
        // 检查当前元素是否匹使用选择器
        if (element.matches(selector)) {
            return element;
        }

        // 如果当前元素不匹配,则查找父元素
        var parent = element.parentNode;

        // 如果没有父元素,则已到达文档的顶部,返回null
        if (!parent) {
            return null;
        }

        // 在父元素的子节点中查找匹配的元素
        var closestElement = parent.querySelector(selector);

        // 如果找到了,则返回该元素
        if (closestElement) {
            return closestElement;
        }

        // 否则递归调用closest函数
        return closest(selector, parent);
    }

    function renderDownload(){
        // $('.card .card-act ul').append(`<li><a title="">下载</a></li>`)
        var ulElements = document.querySelectorAll('.card .card-act ul');
        console.log("uls:::", ulElements)
        ulElements.forEach(function(ul) {


            var cardFeed =  closest('.card-feed', ul);
            if (!cardFeed) return

            var newLi = document.createElement('li');
            var newA = document.createElement('a');
            newA.title = '';
            newA.textContent = '下载视频';

            // 在这里,cardFeed就是<ul>元素最近的具有'card-feed'类的祖先元素
            // console.log(cardFeed);
            var cardVideoSrc = cardFeed.querySelector('video')?.src
            if(cardVideoSrc){
                // console.log(cardVideoSrc);
                newA.href=cardVideoSrc
                newLi.appendChild(newA);
                ul.appendChild(newLi);
            }
        })
    }

    function renderDownloadImg(){
        // $('.card .card-act ul').append(`<li><a title="">下载</a></li>`)
        var ulElements = document.querySelectorAll('.card .card-act ul');
        console.log("uls:::", ulElements)
        ulElements.forEach(function(ul) {


            var cardFeed = closest('.card-feed', ul);
            if (!cardFeed) return

            var newLi = document.createElement('li');
            var newA = document.createElement('a');
            newA.title = '';
            newA.textContent = '下载图片';

            // 在这里,cardFeed就是<ul>元素最近的具有'card-feed'类的祖先元素
            // console.log(cardFeed);

            var imgSrc = [...cardFeed.querySelectorAll('img')].filter(x=>x.src.indexOf('thumb150') > 0).map(x => x.src.replaceAll('thumb150', 'large'));
            if(imgSrc && imgSrc.length > 0){
                console.log("imgSrc:::", imgSrc);
                newA.href='javascript:void(0);'
                newLi.appendChild(newA);


                newA.addEventListener('click', async () => {
                    const imageUrls = imgSrc;
                    console.log("imageUrls:::", imageUrls);
                    const zip = new JSZip();
                    const promises = imageUrls.map(async (url, index) => {
                        const resp = await fetch(url);
                        if (!resp.ok) {
                            throw new Error(`Failed to fetch ${url}`);
                        }
                        const blob = await resp.blob();
                        zip.file(`image${index + 1}.${url.split('.').pop()}`, blob);
                    });

                    try {
                        await Promise.all(promises);
                        const content = await zip.generateAsync({ type: 'blob' });
                        saveAs(content, 'images.zip');
                    } catch (error) {
                        console.error('Error downloading images or creating ZIP:', error);
                    }
                });
                ul.appendChild(newLi);
            }
        });
    }

    ifExist(".thumbnail", renderDownload, 100)
    ifExist(".media", renderDownloadImg, 100)
})();