Greasy Fork

视频嗅探

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

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

// ==UserScript==
// @name         视频嗅探
// @namespace    http://tampermonkey.net/
// @version      0.5
// @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
// @noframes
// @grant        unsafeWindow
// @grant        GM_addElement
// @grant        GM_download
// @grant        GM_setClipboard
// @grant        GM_xmlhttpRequest
// @connect      *
// ==/UserScript==

(function() {
    var n=1 //默认关闭 1关闭,0开启
    let URLs = [];
    unsafeWindow.GM_D = [];
    var mn = -1
    $("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;'>" +
                    "<div id='redPoint' style='width: 5px;height: 5px;position: fixed;top: -25px;right: 30px;font-size: 50px;color: red;font-weight: 400;display:none; '>.</div>"+
                    "<span style='font-size: 30px;line-height: 30px;'>+</span>" +
                    "</div>")

    $(".MyUrls").append("<div class='downloadUrl' style='padding: 5px 0;height: 30px;'> 0、<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='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 (mn=="1"||mn==1){
                $("#MyUpDown span").text('+')
            }else {
                $("#MyUpDown span").text('–')
                $("#redPoint").css("display","none")
            }
            mn = -mn;
        });
    })
    $("body>[id!=MyUpDown][id!=MyUrls]").click(function () {
        if($("#MyUrls").css("display")!="none"){
            $("#MyUpDown").click()
        }
    })
    functionAll("")

    function functionAll(u){
        //跳转链接
        $(".GoUrl"+u).click(function (){
            var url = $(this).prevAll("p").attr("title")
            var link = document.createElement('a');
            link.href = url;
            link.target="_blank";
            link.click();
            link.remove();
        })
        //复制链接
        $(".CopyUrl"+u).click(function (){
            var url = $(this).prevAll("p").attr("title")
            GM_setClipboard(url);
            $(this).text("已复制")
        })
        //下载链接
        $(".SaveUrl"+u).click(function (){
            //$(obj).attr("disabled","disabled")
            var that = $(this)
            var url = $(that).prevAll(".downUrl"+u).val()
            if(url==undefined||url.trim()==''){
                url = $(that).prevAll(".downUrl"+u).attr('title')
                if(url==undefined||url.trim()==''){return;}
            }
            var name = $(that).prevAll(".downName"+u).val()
            if(name==undefined||name.trim()==""){
                name = $('title').text()
                if(name==undefined||name.trim()==""){
                    name = url.split("/").pop().split("?")[0]
                    if(name==undefined||name.trim()==""){
                        name = "video.mp4"
                    }
                }
            }
            if(! /\.[\w]+$/.test(name)){ name = name + ".mp4"}
            //console.log(name,url)
            $(that).css("display","none").next('.StopSaveUrl'+u).css("display","inline-block")
            GM_xmlhttpRequest({
                method: "HEAD",
                fetch: true,
                url: url,
                onerror: function(x) {
                    $(that).text("错误").css("display","inline-block").next(".StopSaveUrl"+u).css("display","none").text("0%");
                },
                onload: function(response) {
                    if( response.status /100 >=4){
                        $(that).text("错误").css("display","inline-block").next(".StopSaveUrl"+u).css("display","none").text("0%");
                        return;
                    }
                    var Length =response.responseHeaders.match(/content-length:\s*[\d]+\s*content-type/im)[0].match(/\d+/)[0]
                    Length = parseInt(Length);
                    var RangeSize = parseInt((Length/5).toFixed(0))
                    var request = [];
                    var blob = [];
                    var loadSize = [];
                    var xhrs = 0
                    for(var i=0,z=0;i<Length;i=i+RangeSize,z++){
                        var range_start=i,range_end=i+RangeSize-1;
                        if (range_end+1>=Length) {range_end = Length}
                        //console.log(range_start,range_end)
                        eval('function onprogress'+z+' (event){'+
                             'loadSize['+z+'] = event.loaded;'+
                             'var x =0;'+
                             'loadSize.forEach(function(item){'+
                             '    x = x + item'+
                             '});'+
                             'var loaded = parseInt(x / Length * 100);'+
                             'if(loaded==100){'+
                             '     $(that).text("下载").css("display","inline-block").next(".StopSaveUrl'+u+'").css("display","none");'+
                             '}else{'+
                             '     $(that).next(".StopSaveUrl'+u+'").text(loaded+"%"); '+
                             //'     console.log(loaded+"%")'+
                             '}'+
                             '}'+
                             'request['+z+'] = GM_xmlhttpRequest({'+
                             'method: "GET",'+
                             'url: url,'+
                             'fetch: false,'+
                             'responseType: "arraybuffer",'+
                             'headers: { "Range":"bytes="+range_start+"-"+range_end},'+
                             'onprogress: onprogress'+ z +','+
                             'onload: function(response) {'+
                             '    blob[' + z + '] = new Blob([response.response]);' +
                             //'    console.log(blob);' +
                             '    var x=0;' +
                             '    loadSize.forEach(function(item){' +
                             '        x = x + item' +
                             '    });' +
                             '    if (x == Length) {' +
                             '       var link = document.createElement("a");' +
                             '       link.href = window.URL.createObjectURL(new Blob(blob));' +
                             '       link.download = name;' +
                             '       link.click();' +
                             '       link.remove();' +
                             '       $(that).text("下载").css("display","inline-block").next(".StopSaveUrl'+u+'").css("display","none").text("0%");'+
                             '    }' +
                             '},'+
                             'onabort: function(){'+
                             //'$(that).text("继续").css("display","inline-block").next(".StopSaveUrl1").css("display","none").text("0%");'+
                             'console.log("error!");'+
                             '},'+
                             'onerror: function(x) {'+
                             '$(that).text("错误").css("display","inline-block").next(".StopSaveUrl'+u+'").css("display","none").text("0%");'+
                             'console.log("error!");'+
                             'request['+z+'].forEach(function(item){'+
                             'item.abort()'+
                             '})'+
                             '},'+
                             '});')
                    }
                    //console.log(request)
                    var num =GM_D.push(request)
                    $(that).next('.StopSaveUrl'+u).data('num',num-1)
                }
            });
        })
        //停止
        $(".StopSaveUrl"+u).click(function (){
            var num = $(this).data("num")
            GM_D[num].forEach(function(item){
                item.abort()
            })
            $(this).css("display","none").text("0%").prev(".SaveUrl"+u).text("继续").css("display","inline-block");
        })
    }



    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,m,length=$('.isUrl').length;
        var scripts =getNetworkRequsts()
        scripts.forEach(function (x,i) {
            if (x.initiatorType === "xmlhttprequest") {
                z = x.name.trim()

                if(/m3u8/.test(x.name) && !/\.ts/.test(x.name)){
                    if(! URLs.includes(z) ){
                        m = URLs.push(z)-1
                        //console.log('type: m3u8 , url: ' + x.name)
                        $(".urlnone").remove()
                        $(".MyUrls").append("<div class='isUrl' style='height: 30px;'> "+(m+1)+"、<p class='downUrl"+m+"' 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;' title='"+z+"'>"+z+"</p><button class='GoUrl"+m+"' style='margin-left: 5px;height:20px;width: 40px;padding: 0;border: none;background: white;border-radius:10px;cursor: pointer;'>访问</button><button class='CopyUrl"+m+"' style='margin-left: 5px;height:20px;width: 40px;padding: 0;border: none;background: white;border-radius:10px;cursor: pointer;'>复制</button><button class='SaveUrl"+m+"' style='display:none;margin-left: 5px;height: 20px;width: 40px;padding: 0;border: none;background: white;border-radius:10px;cursor: pointer;'>下载</button><button class='StopSaveUrl"+m+"' style='display: none;margin-left: 5px;height: 20px;width: 40px;padding: 0;border: none;background: white;border-radius:10px;cursor: pointer;'>0%</button></div>")
                        functionAll(m)
                    }
                }else if(/\.mp4$/.test(z.split('?')[0])){
                    if(! URLs.includes(z) ){
                        m =URLs.push(z)-1
                        //console.log('type: m3u8 , url: ' + x.name)
                        $(".urlnone").remove()
                        $(".MyUrls").append("<div class='isUrl' style='height: 30px;'> "+(m+1)+"、<p class='downUrl"+m+"' 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;' title='"+z+"'>"+z+"</p><button class='GoUrl"+m+"' style='margin-left: 5px;height:20px;width: 40px;padding: 0;border: none;background: white;border-radius:10px;cursor: pointer;'>访问</button><button class='CopyUrl"+m+"' style='margin-left: 5px;height:20px;width: 40px;padding: 0;border: none;background: white;border-radius:10px;cursor: pointer;'>复制</button><button class='SaveUrl"+m+"' style='margin-left: 5px;height: 20px;width: 40px;padding: 0;border: none;background: white;border-radius:10px;cursor: pointer;'>下载</button><button class='StopSaveUrl"+m+"' style='display: none;margin-left: 5px;height: 20px;width: 40px;padding: 0;border: none;background: white;border-radius:10px;cursor: pointer;'>0%</button></div>")
                        functionAll(m)
                    }
                }
            }
            if (x.initiatorType === "video" && !/\.jpg/.test(x.name)) {
                z = x.name.trim()
                if(! URLs.includes(z) ){
                    m =URLs.push(z)-1
                    //console.log('type: video , url: ' + x.name)
                    $(".urlnone").remove()
                    $(".MyUrls").append("<div class='isUrl' style='height: 30px;'> "+(m+1)+"、<p  class='downUrl"+m+"' 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;' title='"+z+"'>"+z+"</p><button class='GoUrl"+m+"' style='margin-left: 5px;height:20px;width: 40px;padding: 0;border: none;background: white;border-radius:10px;cursor: pointer;'>访问</button><button class='CopyUrl"+m+"' style='margin-left: 5px;height:20px;width: 40px;padding: 0;border: none;background: white;border-radius:10px;cursor: pointer;'>复制</button><button class='SaveUrl"+m+"' style='margin-left: 5px;height: 20px;width: 40px;padding: 0;border: none;background: white;border-radius:10px;cursor: pointer;'>下载</button><button class='StopSaveUrl"+m+"' style='display: none;margin-left: 5px;height: 20px;width: 40px;padding: 0;border: none;background: white;border-radius:10px;cursor: pointer;'>0%</button></div>")
                    functionAll(m)
                }
            }
        })
        $("video").each(function () {
            if(!/^blob:/.test(this.currentSrc)){
                z = this.currentSrc.trim()
                if(! URLs.includes(z)&& this.currentSrc!=""){
                    m =URLs.push(z)-1
                    //console.log('type: video , url: ' + this.currentSrc)
                    $(".urlnone").remove()
                    $(".MyUrls").append("<div class='isUrl' style='height: 30px;'> "+(m+1)+"、<p class='downUrl"+m+"' 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;' title='"+z+"'>"+z+"</p><button class='GoUrl"+m+"' style='margin-left: 5px;height:20px;width: 40px;padding: 0;border: none;background: white;border-radius:10px;cursor: pointer;'>访问</button><button class='CopyUrl"+m+"' style='margin-left: 5px;height:20px;width: 40px;padding: 0;border: none;background: white;border-radius:10px;cursor: pointer;'>复制</button><button class='SaveUrl"+m+"' style='margin-left: 5px;height: 20px;width: 40px;padding: 0;border: none;background: white;border-radius:10px;cursor: pointer;'>下载</button><button class='StopSaveUrl"+m+"' style='display: none;margin-left: 5px;height: 20px;width: 40px;padding: 0;border: none;background: white;border-radius:10px;cursor: pointer;'>0%</button></div>")
                    functionAll(m)
                }
            }
            $(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').trim()
                    }else{
                        z = $(this).attr('src').trim()
                    }
                    if(! URLs.includes(z) && z != ""){
                        m =URLs.push(z)-1
                        //console.log('type: src , url: ' + z)
                        $(".urlnone").remove()
                        $(".MyUrls").append("<div class='isUrl' style='padding: 5px 0;height: 30px;'> "+(m+1)+"、<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;' title='"+z+"'>"+z+"</p><button class='GoUrl"+m+"' style='margin-left: 5px;height:20px;width: 40px;padding: 0;border: none;background: white;border-radius:10px;cursor: pointer;'>访问</button><button class='CopyUrl"+m+"' style='margin-left: 5px;height:20px;width: 40px;padding: 0;border: none;background: white;border-radius:10px;cursor: pointer;'>复制</button><button class='SaveUrl"+m+"' style='margin-left: 5px;height: 20px;width: 40px;padding: 0;border: none;background: white;border-radius:10px;cursor: pointer;'>下载</button><button class='StopSaveUrl"+m+"' style='display: none;margin-left: 5px;height: 20px;width: 40px;padding: 0;border: none;background: white;border-radius:10px;cursor: pointer;'>0%</button></div>")
                        functionAll(m)
                    }
                }
            })
        })
        if($('.isUrl').length > length){
            if($("#MyUrls").css("display")=="none"){
                $("#redPoint").css("display","block")
                if(n==0){
                    $("#MyUpDown").click()
                    n = 1
                }
            }
        }
    }
})();