🎉 欢迎访问GreasyFork.Org 镜像站!本镜像站由公众号【爱吃馍】搭建,用于分享脚本。联系邮箱📮

Greasy fork 爱吃馍镜像

自动下载微信公众号文章中的视频

自动下载微信公众号文章视频

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

You will need to install an extension such as Tampermonkey to install this script.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

🚀 安装遇到问题?关注公众号获取帮助

公众号二维码

扫码关注【爱吃馍】

回复【脚本】获取最新教程和防失联地址

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

🚀 安装遇到问题?关注公众号获取帮助

公众号二维码

扫码关注【爱吃馍】

回复【脚本】获取最新教程和防失联地址

// ==UserScript==
// @name         自动下载微信公众号文章中的视频
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  自动下载微信公众号文章视频
// @author       Zep
// @match        https://mp.weixin.qq.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=qq.com

// @grant        GM_log
// @grant        GM_xmlhttpRequest
// @grant        GM_download
// @grant        GM_addStyle
// @require      https://lib.baomitu.com/axios/0.27.2/axios.min.js
// @require      https://lib.baomitu.com/jquery/1.12.4/jquery.min.js
// @license MIT
// ==/UserScript==

(()=>{
    console.log('axios', axios)
    function downloadVideo1(url) {
        // 这是传统的下载方式
        const downloadFileA = unsafeWindow.document.createElement('a')
        unsafeWindow.document.body.append(downloadFileA)
        downloadFileA.href = url
        // http://mpvideo.qpic.cn/0bc3cyabeaaa2maoapqhensfafwdcilaaeqa.f10002.mp4?dis_k=97a32be63138ce2a2f2bde95e491119e&dis_t=1695370394&play_scene=10120&auth_info=Ws+SvC4/Xkm+rqDbJXVtXXtmQlMRLHRjWHgdFWRDLz5hUEkyPwVVHDgFMjpFNlRSbzA=&auth_key=409cd067a1d042d130c471012ecfb8fa&vid=wxv_2829481345448984576&format_id=10002&support_redirect=0&mmversion=false
        const filenameArr = url.split('?')[0].split('/')
        const filename = filenameArr[filenameArr.length - 1]
        downloadFileA.download = filename
        downloadFileA.rel = 'noopener noreferrer'
        // downloadFileA.click()
        unsafeWindow.document.body.removeChild(downloadFileA)
    }

    function downloadVideo2(url) {
        axios({
            method: 'get',
            url: url,
            // 必须显式指明响应类型是一个Blob对象,这样生成二进制的数据,才能通过window.URL.createObjectURL进行创建成功
            responseType: 'blob',
        }).then((res) => {
            if (!res) {
                return
            }
            // 将lob对象转换为域名结合式的url
            let blobUrl = window.URL.createObjectURL(res.data)
            let link = document.createElement('a')
            document.body.appendChild(link)
            link.style.display = 'none'
            link.href = blobUrl
            // 设置a标签的下载属性,设置文件名及格式,后缀名最好让后端在数据格式中返回
            const filenameArr = url.split('?')[0].split('/')
            const filename = filenameArr[filenameArr.length - 1]
            link.download = filename
            // 自触发click事件
            link.click()
            document.body.removeChild(link)
            window.URL.revokeObjectURL(blobUrl);
        })
    }


    function downloadVideo3(url) {
        GM_xmlhttpRequest({
            url:"url",
            method :"GET",
            headers: {
                // "Content-type": "application/x-www-form-urlencoded",
                "Host": "mpvideo.qpic.cn",

            },
            responseType: 'blob',
            onload:function(xhr){
                console.log("success", xhr);
                // 将lob对象转换为域名结合式的url
                // let blobUrl = window.URL.createObjectURL(xhr.response)
                var blob = this.response;
                var reader = new FileReader();

                reader.readAsDataURL(blob); // 转换为base64,可以直接放入a表情href

                reader.onload = function (e) {
                    let link = document.createElement('a')
                    document.body.appendChild(link)
                    link.style.display = 'none'
                    link.href = e.target.result
                    // 设置a标签的下载属性,设置文件名及格式,后缀名最好让后端在数据格式中返回
                    const filenameArr = url.split('?')[0].split('/')
                    const filename = filenameArr[filenameArr.length - 1]
                    link.download = filename
                    // 自触发click事件
                    link.click()
                    document.body.removeChild(link)
                    // window.URL.revokeObjectURL(blobUrl);
                };

                // console.log('blobUrl', blobUrl)

            }
        });


    }

    console.log('GM_xmlhttpRequest', GM_xmlhttpRequest)





    function promise_GM_download(url,i, filename, options = {}){

        return new Promise((resolve, reject) => {
            GM_download({
                url: url,
                name: filename, //不填则自动获取文件名
                saveAs: true, //布尔值,显示"保存为"对话框
                onerror: function (error) {
                    //如果下载最终出现错误,则要执行的回调
                    // console.log(`${filename}下载失败,请重试!`,error)

                    reject(error)

                },
                onprogress: (pro) => {
                    //如果此下载取得了一些进展,则要执行的回调
                    // console.log(pro.loaded) //文件加载量
                    // console.log(pro.totalSize) //文件总大小
                    const pecentage = (pro.loaded / pro.totalSize).toFixed(2) * 100
                    // console.log('.percentage'+ i, 'percentage', pecentage)

                    $('.percentage'+ i).text(pecentage + '%')
                    $('.progress'+ i).val(pecentage)
                    // console.log(`${filename}下载进度:${pecentage}%`)
                },
                ontimeout: () => {
                    //如果此下载由于超时而失败,则要执行的回调
                },
                onload: () => {
                    //如果此下载完成,则要执行的回调
                    // console.log(`${filename}下载成功`)
                    resolve(`${filename}下载成功`)
                },
                ...options
            })


        })

    }



    async function downloadVideo4(url,i, filename) {
        try {
            const res = await promise_GM_download(url,i, filename,{})
            console.log(res)
        }catch(err) {

            $('.error'+ i).removeClass('hiddenTip')
            console.log(err)
        }
        /* GM_download({
            url: url,
            name: filename, //不填则自动获取文件名
            saveAs: true, //布尔值,显示"保存为"对话框
            onerror: function (error) {
                //如果下载最终出现错误,则要执行的回调
                console.log(`${filename}下载失败,请重试!`,error)
            },
            onprogress: (pro) => {
                //如果此下载取得了一些进展,则要执行的回调
                // console.log(pro.loaded) //文件加载量
                // console.log(pro.totalSize) //文件总大小
                const pecentage = pro.loaded / pro.totalSize * 100
                console.log(`${filename}下载进度:${pecentage}%`)
            },
            ontimeout: () => {
                //如果此下载由于超时而失败,则要执行的回调
            },
            onload: () => {
                //如果此下载完成,则要执行的回调
                console.log(`${filename}下载成功`)
            }
        })
        */
    }

    // 往页面上注入弹窗页面
    function addPage() {
        GM_addStyle( `
            .myPage {
           position: fixed;
    top: 50%;
    right: 0;
    padding: 10px;
    background: #eee;
    min-height: 500px;
    width: 500px;
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    border: 2px solid deepskyblue;
    transform: translate(0%, -50%);
      }
      .title {
        color: deepskyblue;
        font-size: 18px;
        margin: 10px 0;
        font-weight: 700;
      }
      .list {
        /* display: flex;
        flex-direction: column;
        flex-wrap: wrap;
        align-items: flex-start; */
        overflow-x: auto;
        height: 400px;
      }
      .list-title {
        font-size: 14px;
      }
      .list-item {
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        padding: 5px;
      }
      .top {
          width: 100%;
        display: flex;
        align-items: flex-start;
        justify-content: flex-start;
      }
      .bottom {
        width: 100%;
        display: flex;
        justify-content: flex-start;
      }
      .error {
        font-size: 12px;
        color: red;
        width: 100%;
        display: flex;
        justify-content: flex-start;
        align-items: center;
        margin: 0 10px;
      }
      .hiddenTip {
        display: none!important;
      }
      .error-tip {

      }
      .progress {
        margin: 0 10px;
      }
      .retryBtn {
        padding: 5px;
        color: #fff;
        background-color: #409eff;
        border: none;
        border-radius: 10%;
        font-size: 12px;
      }
      .line {
        width: 100%;
        height: 1px;
        background-color: #fff;
        margin: 10px 0;
      }
        `)
        const div = document.createElement('div')
        div.classList.add('myPage');
        div.innerHTML = `
     <div class="title">自动下载微信公众号文章中的所有视频</div>
      <div class="list-title">该页面共存在<span class='count'>10</span>个视频文件:</div>
      <div class="list">



      </div>

     `
     document.body.append(div)

    }





    window.onload = function(){
        $('body').on('click', '.retryBtn', function(e) {
            let url = e.target.attributes.getNamedItem('data-src').nodeValue
            const filename = e.target.attributes.getNamedItem('data-filename').nodeValue
            const i = e.target.attributes.getNamedItem('data-i').nodeValue
            // 点击事件处理程序
            console.log('点击了动态添加的元素', e, url,filename,i);
            // url = url.replace('12345', '')
            $('.error'+ i).addClass('hiddenTip')
            downloadVideo4(url, i, filename)

        })
        console.log('onload')
        addPage()
        const videos = window.document.querySelectorAll('video')
        $('.count').text(videos.length)
        for(let i = 0; i < videos.length; i++) {
            let url = videos[i].getAttribute('src')
            const filenameArr = url.split('?')[0].split('/')
            let filename = i+1 + '-' + filenameArr[filenameArr.length - 1]
            const suffixs = filename.split('.')
            const suffix = suffixs[suffixs.length - 1]
            filename =  i+1 + '-' + new Date().getTime() + '.' + suffix
            // if(i === 1) {
            //    url = '12345' + url
            // }

            $('.list').append(`
            <div class="list-item">
          <div class="top">
            <div>${i+1}.</div>
            <div>${filename}:</div>
          </div>
          <div class="bottom">
            <progress class="progress${i+1}" value="0" max="100"></progress>
            <div class="percentage${i+1}">0%</div>
          </div>
          <div class="error hiddenTip error${i+1}">
            <div class="error-tip error-tip${i+1}">下载失败,请重试!</div>
            <button class="retryBtn" data-src=${url} data-i=${i+1} data-filename=${filename}>重试</button>
          </div>
          <div class="line"></div>
        </div>

            `)

            downloadVideo4(url, i+1, filename)
        }

    }


}
)()