Greasy Fork

视频嗅探

自动嗅探页面上的视频资源,将链接展示出来,并提供复制和下载方法(除部分流媒体不能下载,需要专用的下载器)。

目前为 2023-07-05 提交的版本。查看 最新版本

// ==UserScript==
// @name         视频嗅探
// @namespace    http://tampermonkey.net/
// @version      0.3
// @description  自动嗅探页面上的视频资源,将链接展示出来,并提供复制和下载方法(除部分流媒体不能下载,需要专用的下载器)。
// @author       geigei717
// @license      MIT
// @match        https://*/*
// @match        http://*/*
// @icon         https://img-blog.csdnimg.cn/20181221195058594.gif
// @require      https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js
// @grant        GM_addElement
// @grant        GM_download
// @grant        GM_setClipboard
// ==/UserScript==

(function() {
    GM_addElement('script', {
        src: 'https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js',
        type: 'text/javascript'
    });
    let URLs = [];
    unsafeWindow.GM_D = [];
    unsafeWindow.download = function (url,name){
        GM_download(url, name);
    }
    //$("head").append('<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> ')
    var m = -1
    var n=1  //默认关闭 1关闭,0开启
    $("body").append("<div id='MyUrls' style='width: 400px;background-color: #3e8f3e;color: black;position: fixed;top: 0;right: 0;z-index: 99999;border-radius: 10px;display: none;'>" +
            "<div style='height: 30px;font-size: 20px;'>&nbsp&nbsp&nbsp视频链接:<span style='font-size: 10px;color:red;'>部分m3u8等流媒体无法下载,需要专用下载器</span></div>" +
            "<hr style='border-color: black;margin: 5px 5px'>" +
            "<div class='MyUrls' style='margin: 10px 10px;max-height: 500px;overflow-y: auto;'>" +
            "   <div class='urlnone' style='height: 30px;color: red'> 暂时没有嗅探到视频资源</div>" +
            "</div>" +
            "</div>")
            .append("<div id='MyUpDown' style='width: 30px;height: 30px;color: black;background-color: #3e8f3e;position: fixed;top: 0;right: 0;z-index: 100000;font-size: 20px;line-height: 30px;text-align: center;cursor: pointer;border-radius: 30px;'>" +
                    "<span style='font-size: 30px;line-height: 30px;'>+</span>" +
                    "</div>")
    $(".MyUrls").append("<div class='downloadUrl' style='padding: 5px 0;height: 30px;'> <input  class='downUrl'  style='position: relative;top: -2px;font-size: 12px;width: 200px;display: inline-block;max-width: 240px;word-wrap: break-word;white-space: nowrap;text-overflow: ellipsis;overflow: hidden;margin: 0px;height: 20px;border: 1px solid white;border-radius: 5px;padding: 0 5px; background: white;color:black' placeholder='请输入要下载的视频链接:'>  <input class='downName' style='position: relative;top: -2px;font-size: 12px;width: 70px;display: inline-block;max-width: 240px;word-wrap: break-word;white-space: nowrap;text-overflow: ellipsis;overflow: hidden;margin: 0px;height: 20px;border: 1px solid white;border-radius: 5px;padding: 0 5px; background: white;color:black'  placeholder='请输入文件名'><button class='SaveUrl1' style='margin-left: 5px;height: 20px;width: 40px;padding: 0;border: none;background: white;border-radius:10px;cursor: pointer;'>下载</button><button class='StopSaveUrl1' style='display: none;margin-left: 5px;height: 20px;width: 40px;padding: 0;border: none;background: white;border-radius:10px;cursor: pointer;'>0%</button></div>")
    //下载链接
    $(".SaveUrl1").click(function (){
        //$(obj).attr("disabled","disabled")
        var that = $(this)
        $(that).css("display","none").next('.StopSaveUrl1').css("display","inline-block")
        var url = $(that).prevAll(".downUrl").val()
        var name = $(that).prevAll(".downName").val()
        if(name.trim()==""||name==undefined){
            name = url.split("/").pop().split("?")[0]
            if(name.trim() ==''||name==undefined){ name = "video.mp4"}
        }
        if(! /\.[\w]+$/.test(name)){ name = name + ".mp4"}
        const download = GM_download({
            url: url,
            name: name,
            onprogress : function (event) {
                if (event.lengthComputable) {
                    var loaded = parseInt(event.loaded / event.total * 100);
                    if(loaded==100){
                        $(that).text("下载").css("display","inline-block").next('.StopSaveUrl1').css("display","none")
                    }else{
                        $(that).next('.StopSaveUrl1').text(loaded+"%")
                    }
                }
            },
            onload : function () {
                $(that).text("下载").css("display","inline-block").next('.StopSaveUrl1').css("display","none").text("0%")
            },
            onerror : function () {
                $(that).text("继续").css("display","inline-block").next('.StopSaveUrl1').css("display","none")
            }
        });
        var num =GM_D.push(download)
        $(that).next('.StopSaveUrl1').data('num',num-1)
    })
    $(".StopSaveUrl1").click(function (){
            var num = $(this).data("num")
            GM_D[num].abort()
            //GM_D.splice(num,1);
    })

    for(var i=0;i<100;i++){
        $(".MyUrls").append("<div class='noneUrl' style='padding: 5px 0;height: 30px;display:none;'> <p style='position: relative;top: 5px;font-size: 12px;width: 200px;display: inline-block;max-width: 240px;word-wrap: break-word;white-space: nowrap;text-overflow: ellipsis;overflow: hidden;margin: 0px;height: 20px;border: 1px solid white;border-radius: 5px;padding: 0 5px; background: white;' ></p><button class='GoUrl' style='margin-left: 5px;height:20px;width: 40px;padding: 0;border: none;background: white;border-radius:10px;cursor: pointer;'>访问</button><button class='CopyUrl' style='margin-left: 5px;height:20px;width: 40px;padding: 0;border: none;background: white;border-radius:10px;cursor: pointer;'>复制</button><button class='SaveUrl' style='margin-left: 5px;height: 20px;width: 40px;padding: 0;border: none;background: white;border-radius:10px;cursor: pointer;'>下载</button><button class='StopSaveUrl' style='display: none;margin-left: 5px;height: 20px;width: 40px;padding: 0;border: none;background: white;border-radius:10px;cursor: pointer;'>0%</button></div>")
    }
    $("#MyUpDown").click(function () {
        $("#MyUrls").slideToggle("slow", function () {
            if (m=="1"){
                $("#MyUpDown span").text('+')
            }else {
                $("#MyUpDown span").text('–')
            }
            m = -m;
        });
    })

    //复制链接
    $(".GoUrl").click(function (){
        var url = $(this).prevAll("p").attr("title")
        window.open(url)
    })
     //复制链接
    $(".CopyUrl").click(function (){
        var url = $(this).prevAll("p").attr("title")
        GM_setClipboard(url);
        $(this).text("已复制")
    })

    //下载链接
    $(".SaveUrl").click(function (){
        //$(obj).attr("disabled","disabled")
        var that = $(this)
        $(that).css("display","none").next('.StopSaveUrl').css("display","inline-block")
        var url = $(that).prevAll("p").attr("title")
        var name = url.split("/").pop().split("?")[0]
        if(name==''||name==undefined){ name = "video.mp4"}
        if(! /\.[\w]+$/.test(name)){ name = name + ".mp4"}
        const download = GM_download({
            url: url,
            name: name,
            onprogress : function (event) {
                if (event.lengthComputable) {
                    var loaded = parseInt(event.loaded / event.total * 100);
                    if(loaded==100){
                        $(that).text("下载").css("display","inline-block").next('.StopSaveUrl').css("display","none")
                    }else{
                        $(that).next('.StopSaveUrl').text(loaded+"%")
                    }
                }
            },
            onload : function () {
                $(that).text("下载").css("display","inline-block").next('.StopSaveUrl').css("display","none").text("0%")
            },
            onerror : function () {
                $(that).text("继续").css("display","inline-block").next('.StopSaveUrl').css("display","none")
            }
        });
        var num =GM_D.push(download)
        $(that).next('.StopSaveUrl').data('num',num-1)
    })
    $(".StopSaveUrl").click(function (){
        var num = $(this).data("num")
        GM_D[num].abort()
    })


    function getNetworkRequsts(){
       return performance.getEntriesByType("resource").filter((entry) => {
            return entry.initiatorType === "xmlhttprequest"||entry.initiatorType === "video";
        });
    }
    var observer = new PerformanceObserver(perf_observer);
    observer.observe({entryTypes: ["resource"]})

    function perf_observer(list,observer){
        var z
        var scripts =getNetworkRequsts()
        scripts.forEach(function (x,i) {
            if (x.initiatorType === "xmlhttprequest") {
                z = x.name
                if(/m3u8/.test(x.name) && !/\.ts/.test(x.name)){
                if(! URLs.includes(z) ){
                    URLs.push(z)
                    //console.log('type: m3u8 , url: ' + x.name)
                    $(".urlnone").remove()
                    $(".MyUrls .noneUrl:first").css("display","block").attr("class","isUrl").children("p").attr('title',z).text(z).nextAll(".SaveUrl").css("display","none")
                    //$(".MyUrls").append("<div style='height: 30px;'> <input style='width: 240px' value='' readonly><button class='CopyUrl' style='margin-left: 5px;height: 24px;width: 50px;padding: 0;border: none;background: white;border-radius:0;'>复制</button>")
                }
                }else if(/\.mp4$/.test(z.split('?')[0])){
                    if(! URLs.includes(z) ){
                    URLs.push(z)
                    //console.log('type: m3u8 , url: ' + x.name)
                    $(".urlnone").remove()
                    $(".MyUrls .noneUrl:first").css("display","block").attr("class","isUrl").children("p").attr('title',z).text(z)
                    //$(".MyUrls").append("<div style='height: 30px;'> <input style='width: 240px' value='' readonly><button class='CopyUrl' style='margin-left: 5px;height: 24px;width: 50px;padding: 0;border: none;background: white;border-radius:0;'>复制</button>")
                }
                }
            }
            if (x.initiatorType === "video" && !/\.jpg/.test(x.name)) {
                z = x.name
                if(! URLs.includes(z) ){
                    URLs.push(z)
                    //console.log('type: video , url: ' + x.name)
                    $(".urlnone").remove()
                    $(".MyUrls .noneUrl:first").css("display","block").attr("class","isUrl").children("p").attr('title',z).text(z)
                    //$(".MyUrls").append("<div style='height: 30px;'> <input style='width: 240px' value='"+z+"' readonly><button class='CopyUrl' style='margin-left: 5px;height: 24px;width: 50px;padding: 0;border: none;background: white;border-radius:0;'>复制</button><button class='SaveUrl' style='margin-left: 5px;height: 24px;width: 50px;padding: 0;border: none;background: white;border-radius:0;'>下载</button></div>")
                }
            }
        })
        $("video").each(function () {
            if(!/^blob:/.test(this.currentSrc)){
                z = this.currentSrc
                if(! URLs.includes(z)&& this.currentSrc!=""){
                    URLs.push(z)
                    //console.log('type: video , url: ' + this.currentSrc)
                    $(".urlnone").remove()
                    $(".MyUrls .noneUrl:first").css("display","block").attr("class","isUrl").children("p").attr('title',z).text(z)
                    //$(".MyUrls").append("<div style='height: 30px;'> <input style='width: 240px' value='"+z+"' readonly><button class='CopyUrl' style='margin-left: 5px;height:24px;width: 50px;padding: 0;border: none;background: white;border-radius:0;'>复制</button><button class='SaveUrl' style='margin-left: 5px;height: 24px;width: 50px;padding: 0;border: none;background: white;border-radius:0;'>下载</button></div>")
                }
            }
            $(this).find("source").each(function () {
                if($(this).attr('src')!=''&&$(this).attr('src')!=undefined){
                if(!/^(http:|https:)/.test($(this).attr('src'))){
                    z = location.href.split("://")[0] +':'+ $(this).attr('src')
                }else{
                    z = $(this).attr('src')
                }
                if(! URLs.includes(z) && z != ""){
                    URLs.push(z)
                    //console.log('type: src , url: ' + z)
                    $(".urlnone").remove()
                    $(".MyUrls .noneUrl:first").css("display","block").attr("class","isUrl").children("p").attr('title',z).text(z)
                    //$(".MyUrls").append("<div style='height: 30px;'> <input style='width: 240px' value='"+z+"' readonly><button class='CopyUrl'  style='margin-left: 5px;height: 24px;width: 50px;padding: 0;border: none;background: white;border-radius:0;'>复制</button><button class='SaveUrl' style='margin-left: 5px;height: 24px;width: 50px;padding: 0;border: none;background: white;border-radius:0;'>下载</button></div>")
                }
                }
            })
        })
        if(URLs.length>0 &&  $("#MyUrls").css("display")=="none"&& n==0){
            $("#MyUpDown").click()
            n = 1
        }
    }
})();