麒麟听书

麒麟听书爬取具体章节信息

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey, το Greasemonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

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

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Userscripts για να εγκαταστήσετε αυτόν τον κώδικα.

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

Θα χρειαστεί να εγκαταστήσετε μια επέκταση διαχείρισης κώδικα χρήστη για να εγκαταστήσετε αυτόν τον κώδικα.

(Έχω ήδη έναν διαχειριστή κώδικα χρήστη, επιτρέψτε μου να τον εγκαταστήσω!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Έχω ήδη έναν διαχειριστή στυλ χρήστη, επιτρέψτε μου να τον εγκαταστήσω!)

// ==UserScript==
// @name         麒麟听书
// @namespace    czy
// @version      1.0.3
// @description  麒麟听书爬取具体章节信息
// @author       czy
// @icon         https://www.70ts.cc/favicon.ico
// @match        https://www.70ts.cc/tingshu/*
// @grant        GM_xmlhttpRequest
// @grant        unsafeWindow
// @license      MIT
// @connect      none
// @require      http://code.jquery.com/jquery-1.11.0.min.js
// ==/UserScript==

(function () {
    let newList=[];
    let storyName;

    if(parseInt(window.location.href.substring(window.location.href.indexOf("tingshu/")).replace("tingshu/","")) && parseInt(window.location.href.substring(window.location.href.indexOf("tingshu/")).replace("tingshu/",""))!=NaN){
        storyName = "tingshu"+parseInt(window.location.href.substring(window.location.href.indexOf("tingshu/")).replace("tingshu/",""));
    }else{
        storyName = "tingshu";
    }
    console.log("页面加载中")
    console.log("本地存储名:"+storyName)
    if(localStorage.getItem(storyName) != null){
        newList = JSON.parse(localStorage.getItem(storyName));
    }else{
        localStorage.setItem(storyName,JSON.stringify(Array.from(new Set(newList))));
        //window.location.href = $(".jump-list .pg-next")[0].href;
    }
    function unique(arr) {
        // 创建一个Map对象实例
        const res = new Map()
        // 过滤条件:如果res中没有某个键,就设置这个键的值为1
        return arr.filter((arr) => !res.has(arr.bookEpisode) && res.set(arr.bookEpisode, 1))
    }
    window.onload=function(){
        /*jQuery/Zepto弹窗插件 | version:2016-11-30*/
        !function(t){var e=".alert_overlay{position:fixed;width:100%;height:100%;top:0;left:0;z-index:1000;background:rgba(0,0,0,.05);-webkit-backdrop-filter:blur(3px)}.pc .alert_msg{width:320px}.mob .alert_msg{width:260px;border-radius:4px}.alert_msg{box-sizing:border-box;position:absolute;left:50%;top:30%;border:1px solid #ccc;box-shadow:0 2px 15px rgba(0,0,0,.3);background:#fff;transition:all .2s cubic-bezier(.8,.5,.2,1.4);-webkit-transform:translate(-50%,-50%) scale(.5);opacity:0;transform:translate(-50%,-50%) scale(.5)}.alert_show .alert_msg{opacity:1;transform:translate(-50%,-50%) scale(1);-webkit-transform:translate(-50%,-50%) scale(1)}.alert_content{padding:20px 15px;font-size:14px;text-align:left}.alert_tips{position:fixed;z-index:10176523}.pc .alert_buttons{padding:6px;border-top:1px solid #ccc;text-align:right;box-shadow:0 1px 0 #fff inset;background:#eee;-webkit-user-select:none}.pc .alert_buttons .alert_btn{padding:4px 8px;margin:0 2px;border:1px solid #ccc;background:#eee;cursor:pointer;border-radius:2px;font-size:14px;outline:0;-webkit-appearance:none}.pc .alert_buttons .alert_btn:hover{border-color:#ccc;box-shadow:0 1px 2px #ccc;background:#eaeaea}.pc .alert_buttons .alert_btn:active{box-shadow:0 1px 2px #ccc inset;background:#e6e6e6}.pc.alert_tips{top:50px;right:50px}.pc.alert_tips div{background:rgba(0,0,0,.7);position:relative;color:#fff;font-size:16px;padding:10px 15px;border-radius:2px;margin-bottom:20px;box-shadow:0 0 3px #000;display:none;float:right;clear:both}.mob .alert_buttons{text-align:center;border-top:1px solid #ccc;-webkit-user-select:none}.mob .alert_buttons .alert_btn{display:inline-block;width:50%;border:0;height:40px;font-size:14px;outline:0;-webkit-appearance:none;background:#fff;-webkit-tap-highlight-color:transparent;border-radius:0 0 4px 4px}.mob .alert_buttons .alert_btn:only-child{width:100%}.mob .alert_buttons .alert_btn:first-child+.alert_btn{border-left:1px solid #ccc;border-radius:0 0 4px 0}.mob.alert_tips{width:100%;top:55%;pointer-events:none;text-align:center}.mob.alert_tips div{box-sizing:border-box;display:inline-block;padding:15px;border-radius:10px;background:rgba(0,0,0,.7);min-width:50px;max-width:230px;text-align:center;color:#fff;animation:tipsshow 3s .01s ease;-webkit-animation:tipsshow 3s .01s ease;opacity:0}@keyframes tipsshow{0%{opacity:0;transform:scale(1.4) rotateX(-360deg)}20%,80%{opacity:1;transform:scale(1) rotateX(0deg)}to{transform:scale(1.4) rotateX(360deg)}}@-webkit-keyframes tipsshow{0%,to{opacity:0}0%{-webkit-transform:scale(1.4) rotateX(-360deg)}20%,80%{opacity:1;-webkit-transform:scale(1) rotateX(0deg)}to{opacity:0;-webkit-transform:scale(1.4) rotateX(360deg)}}";t("head").append('<style type="text/css">'+e+"</style>"),t._ismob=/i(Phone|Pod)|Android|phone/i.test(navigator.userAgent),t._isalert=t._isload=0,t.alert=function(){if(arguments.length)return t._isalert=1,t.confirm.apply(t,arguments)},t.confirm=function(){var e,o=arguments;if(o.length){var a=o[1],n=function(t){"function"==typeof a?0!=a.call(e,t.data.r)&&e.close():e.close()};e=t('<div class="alert_overlay '+(t._ismob?"mob":"pc")+'"><div class="alert_msg"><div class="alert_content">'+o[0]+'</div><div class="alert_buttons"><button class="alert_btn alert_btn_cancel">取消</button><button class="alert_btn alert_btn_ok">确定</button></div></div></div>').on("contextmenu",!1).on("click",".alert_btn_ok",{r:!0},n).on("click",".alert_btn_cancel",{r:!1},n),t._isload?e.find(".alert_content").css("text-align","center").parent().css({width:"auto",borderRadius:"4px"}).find(".alert_buttons").remove():t._isalert&&e.find(".alert_btn_cancel").remove(),e.appendTo("body").find(".alert_btn_ok").focus(),e.ok=function(t){return e.find(".alert_btn_ok").text(t||"确定"),e},e.cancel=function(t){return e.find(".alert_btn_cancel").text(t||"取消"),e},e.content=function(t){return t&&e.find(".alert_content").html(t),e},e.close=function(){e.one("webkitTransitionEnd transitionEnd",function(){e.remove()}).removeClass("alert_show")},e.addClass("alert_show")}return t._isalert=t._isload=0,e},t.tips=function(e,o){if(e)if(t._ismob)t(".alert_tips").remove(),t('<div class="alert_tips mob"><div>'+e+"</div></div>").appendTo("body").one("webkitAnimationEnd animationEnd",function(){t(this).remove()});else{var a=t(".alert_tips");a.length||(a=t('<div class="alert_tips pc"></div>').appendTo("body")),t("<div>"+e+"</div>").appendTo(a).fadeIn("fast").delay(o||2e3).slideUp("fast",function(){t(this).remove()})}},t.load=function(){t(".alert_overlay").remove(),t._isload=1;var e=t.confirm.call(t,arguments[0]||"加载中,请稍后...");return t.loaded=e.close,e}}($);
        console.log("页面加载完成")
        setTimeout(()=>{
            if(document.getElementById("play") !=null && document.getElementById("play").contentWindow.document.getElementById("jp_audio_0").src !="" && document.getElementById("play").contentWindow.document.getElementById("jp_audio_0").src != undefined){
                //console.log($(".list-book-dt a").text());
                //console.log($(".content h1").text());
                //console.log(document.getElementById("play").contentWindow.document.getElementById("jp_audio_0").src);
                //获取当前页有声书播放信息
                let current = {bookName:$(".list-book-dt a").text(),bookEpisode:$(".content h1").text(),episodeUrl:document.getElementById("play").contentWindow.document.getElementById("jp_audio_0").src};
                newList.push(current)
                localStorage.setItem(storyName,JSON.stringify(Array.from(unique(newList))));
                console.log("爬取了:"+JSON.parse(localStorage.getItem(storyName)).length + "集");
                if($("#nexturl")[0]){
                    setTimeout(()=>{
                        window.location=$("#nexturl")[0].href;//下一页
                    },10);
                }else{
                    alert("分析完毕,下载数据");
                    function sortData(a, b) {
                        //str.substring(str.lastIndexOf("/")).replace(str.substring(str.lastIndexOf(".")),"").replace("/","")
                        return ( (a.episodeUrl.substring(a.episodeUrl.lastIndexOf("/")).replace(a.episodeUrl.substring(a.episodeUrl.lastIndexOf(".")),"").replace("/","")) - (b.episodeUrl.substring(b.episodeUrl.lastIndexOf("/")).replace(b.episodeUrl.substring(b.episodeUrl.lastIndexOf(".")),"").replace("/","")) )
                    }
                    let myList = JSON.parse(localStorage.getItem(storyName));
                    myList.sort(sortData);
                    //将数据转为csv需要的格式
                    let csvString = [
                        ["bookName","bookEpisode","episodeUrl"],
                        ...myList.map(item => [
                            item.bookName,
                            item.bookEpisode.replace("正在播放:",""),
                            item.episodeUrl
                        ])
                    ].map(e => e.join(",")).join('\n')

                    // 导出
                    let link = document.createElement("a")
                    let exportContent = '\uFEFF'
                    let blob = new Blob([exportContent+csvString],{
                        type:'text/plain;charset=utrf-8'
                    })
                    link.id = "download-csv"
                    link.setAttribute("href", URL.createObjectURL(blob))
                    link.setAttribute('download', storyName + ".csv")
                    document.body.appendChild(link)
                    link.click()
                }
            }else if(document.getElementById("play")==null){
                //排序
                function sortData(a, b) {
                    //str.substring(str.lastIndexOf("/")).replace(str.substring(str.lastIndexOf(".")),"").replace("/","")
                    return ( (a.episodeUrl.substring(a.episodeUrl.lastIndexOf("/")).replace(a.episodeUrl.substring(a.episodeUrl.lastIndexOf(".")),"").replace("/","")) - (b.episodeUrl.substring(b.episodeUrl.lastIndexOf("/")).replace(b.episodeUrl.substring(b.episodeUrl.lastIndexOf(".")),"").replace("/","")) )
                }
                function downLoadMyListen(){
                    let myList = JSON.parse(localStorage.getItem(storyName));
                    myList.sort(sortData);
                    //将数据转为csv需要的格式
                    let csvString = [
                        ["bookName","bookEpisode","episodeUrl","bookId"],
                        ...myList.map(item => [
                            item.bookName,
                            item.bookEpisode.replace("正在播放:",""),
                            item.episodeUrl,
                            storyName.replace("tingshu","")
                        ])
                    ].map(e => e.join(",")).join('\n')

                    // 导出
                    let link = document.createElement("a")
                    let exportContent = '\uFEFF'
                    let blob = new Blob([exportContent+csvString],{
                        type:'text/plain;charset=utrf-8'
                    })
                    link.id = "download-csv"
                    link.setAttribute("href", URL.createObjectURL(blob))
                    link.setAttribute('download', storyName + ".csv")
                    document.body.appendChild(link)
                    link.click()
                }
                $.confirm("爬取分析了:"+JSON.parse(localStorage.getItem(storyName)).length + "集,下载数据?",function(e){
                    //点击确定或取消后的回调函数,点击确定e = true,点击取消e = false
                    //return false 可以阻止对话框关闭
                    //this 指向弹窗对象
                    if(e){
                        downLoadMyListen();
                    }
                }).ok('下载').cancel('取消')//支持修改弹窗的按钮文字
            }else{
                alert("失败"+ 'document.getElementById("play").contentWindow.document.getElementById("jp_audio_0").src'+"\n刷新该界面");
                location.reload()
            }
        },100);
    }
})();