// ==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); } })();