您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
漫畫自動連續載入
// ==UserScript== // @name 漫畫閱讀器 // @version 2.2.3 // @namespace 486FF937-D190-42D3-B107-6ED190443E1C // @description 漫畫自動連續載入 // @include /https?:\/\/e[x-]hentai\.org\/s\/\w+\/\w+/ // @include /https?:\/\/www\.dm5\.com\/m\d+/ // @include /https?:\/\/www\.1kkk\.com\/ch\d+-\d+/ // @include /https?:\/\/comicbus\.\w+\/online\/[\w-]+\.html\?ch=\d+/ // @match *://*.manhuagui.com/comic/*/*.html* // @match *://www.cartoonmad.cc/comic/*.html* // @match *://www.gufengmh8.com/manhua/*/*.html* // @match *://www.manhuabei.com/manhua/*/*.html* // @match *://www.manhuafen.com/comic/*/*.html* // @match *://www.36mh.com/manhua/*/*.html* // @match *://www.90mh.com/manhua/*/*.html* // @run-at document-end // @grant GM_xmlhttpRequest // @grant unsafeWindow // ==/UserScript== Element.prototype.offset = function(){ let rect = this.getBoundingClientRect(); return { top: Math.round(scrollY + rect.top), bottom: Math.round(scrollY + rect.top + rect.height) } } Element.prototype.goTo = function(n){ viewport.scrollTop = this.offset().top + (n||0); } function clone (obj) { return JSON.parse(JSON.stringify(obj)) } function log(s){ if(isLog){ console.log(s.toString()); } } function getEl(s, d){ return (d || document).querySelector(s); } function img_loaded(){ this.removeAttribute('style'); //橫圖 if (this.naturalWidth > this.naturalHeight) { this.originalWidth = this.naturalWidth if(this.naturalWidth > max_h_width){ this.style.width = max_h_width + 'px' this.originalWidth = max_h_width }else if(this.naturalWidth < min_h_width){ this.style.width = min_h_width + 'px' this.originalWidth = min_h_width } //直圖 or 正方形 } else { this.originalHeight = this.naturalHeight if (this.naturalHeight < min_v_height) { this.style.height = min_v_height + 'px' this.originalHeight = min_v_height } else if (this.naturalHeight > max_v_height) { this.style.height = max_v_height + 'px' this.originalHeight = max_v_height } } this.onclick = click_RWD; } function img_error(e) { let link = new URL(this.src) let count = parseInt(link.searchParams.get('try'), 10) || 0 if (count < 2) { link.searchParams.set('try', count + 1) this.src = link.href } else { console.log('error', this.src) } } function click_RWD() { if (this.height === this.originalHeight || this.width === this.originalWidth) { let gap = 10 / devicePixelRatio this.style.height = (innerHeight - gap) + 'px' this.style.width = null this.goTo(-gap / 2); } else if (this.originalHeight !== undefined) { this.style.height = this.originalHeight + 'px' this.style.width = null } else { this.style.width = this.originalWidth + 'px' this.style.height = null } } function Img(n){ let pic = new Image(); pic.style.border = '3px dashed #FF0000'; pic.style.maxWidth = max_h_width + 'px'; pic.style.maxHeight = max_v_height + 'px'; pic.onload = img_loaded; pic.onerror = img_error; (function(){ if (picUrls[n - 1]) { pic.src = picUrls[n - 1]; } else { setTimeout(arguments.callee, 500); } })(); return pic; } function bookmark(n){ let d = document.createElement('div'); d.setAttribute('style', 'height: 22px; background: #E6E6E6; margin: 30px 0px; font: bold 18px Arial; color: black;'); d.innerHTML = '第 ' + n + ' 頁'; return d; } function preload(count){ let index = pics.length; let end = index + (count||preCount); if(end > picCount) end = picCount; while(index<end){ log('preload page: ' + (index+1)); pics[index] = Img(index+1); index++; } } function showPics(count){ let end = pageNum + (count||preCount) - 1; if(end > picCount) end = picCount; while(pageNum<=end){ log('show pic: ' + pageNum); picArea.appendChild(pics[pageNum - 1]); picArea.appendChild(bookmark(pageNum)); pageNum++; } } function dm5(){ pageNum = parseInt(getEl('#chapterpager>.current').textContent, 10); picCount = document.head.innerHTML.match(/DM5_IMAGE_COUNT *= *"?(.+?)"?;/)[1]; picArea = getEl('#showimage'); picUrls = new Array(pageNum-1); pics = new Array(pageNum-1); let getPicUrls_error = 0; let DM5_CID = document.head.innerHTML.match(/DM5_CID *= *"?(.+?)"?;/)[1]; let DM5_MID = document.head.innerHTML.match(/DM5_MID *= *"?(.+?)"?;/)[1]; let DM5_VIEWSIGN_DT = document.head.innerHTML.match(/DM5_VIEWSIGN_DT *= *"?(.+?)"?;/)[1]; let DM5_VIEWSIGN = document.head.innerHTML.match(/DM5_VIEWSIGN *= *"?(.+?)"?;/)[1]; (function getPicUrls(){ let xhr = new XMLHttpRequest(); xhr.timeout = 10000; xhr.open('GET', 'chapterfun.ashx?' + 'cid=' + DM5_CID + '&page=' + (picUrls.length+1) + '&_cid=' + DM5_CID + '&_mid=' + DM5_MID + '&_dt=' + DM5_VIEWSIGN_DT + '&_sign=' + DM5_VIEWSIGN ); xhr.onload = function(){ picUrls = picUrls.concat(eval(xhr.responseText)); log('getPicUrls onload: ' + picUrls.slice(-1)); if(picUrls.length < picCount){ // 間隔3秒一次請求,可以一次拿到最大數量20張,小於3秒一次2張,大於3秒最多還是一次20張 setTimeout(function(){ getPicUrls(); },(picUrls.length < 8) ? 0 : 3000); } }; xhr.onerror = function(){ if(++getPicUrls_error < 3){ setTimeout(function(){ getPicUrls(); }, 1000); }else{ alert('getPicUrls error'); } }; xhr.send(); })(); getEl('.rightToolBar').remove(); } function manhuaren(){ pageNum = parseInt(getEl('#chapterpager>.current').textContent, 10); picCount = document.head.innerHTML.match(/DM5_IMAGE_COUNT *= *"?(.+?)"?;/)[1]; picArea = getEl('#showimage'); picUrls = new Array(pageNum-1); pics = new Array(pageNum-1); console.log('https://www.manhuaren.com' + location.pathname) GM_xmlhttpRequest({ 'method': 'GET', 'url': 'https://www.manhuaren.com' + location.pathname, 'timeout': 10000, 'onload': function(res){ let doc = new DOMParser().parseFromString(res.responseText, 'text/html'); eval(doc.scripts[10].innerHTML); picUrls = newImgs; }, 'onerror': function(res){ alert('getPicUrls error'); } }); getEl('.rightToolBar').remove(); } function eh(){ pageNum = parseInt(getEl('.sn span:nth-of-type(1)').textContent, 10); picCount = parseInt(getEl('.sn span:nth-of-type(2)').textContent, 10); picArea = getEl('#i3'); picUrls = new Array(pageNum-1); pics = new Array(pageNum-1); preCount = 2; overRange = 1000; getEl('#i1').removeAttribute('style'); picUrls.push(getEl('#img').src); let getPicUrls_error = 0; (function getPicUrls(url){ if(picUrls.length-pics.length<preCount){ let xhr = new XMLHttpRequest(); xhr.timeout = 10000; xhr.onload = function(){ let doc = new DOMParser().parseFromString(xhr.responseText, 'text/html'); picUrls.push(getEl('#img', doc).src); log('getPicUrls onload: ' + picUrls.length); if(picUrls.length<picCount){ setTimeout(function(){ getPicUrls(getEl('#i3 > a', doc).href); }, 0); } }; xhr.onerror = function(){ if(++getPicUrls_error<3){ setTimeout(function(){ getPicUrls(url); }, 1000); }else{ alert('getPicUrls error'); } }; xhr.open('GET', url); xhr.send(); }else{ log('getPicUrls wait...'); setTimeout(function(){ getPicUrls(url); }, 500); } })(getEl('#i3 > a').href); } function manhuagui(){ // 全局物件 // servs: 圖片 server 相關 // pVars: 從 imgData 中設定出來的,有著當個章節的資訊 // 但因為有了 imgData,這個變數的值都可以計算出來,所以沒啥用 // SMH: 頁面加載漫畫的核心物件 pageNum = unsafeWindow.pVars.page; picCount = unsafeWindow.cInfo.len; pics = new Array(pageNum - 1); picArea = getEl('table.pr').parentElement; picArea.setAttribute('align', 'center'); getEl('#servList').remove(); getEl('.sub-btn').remove(); getEl('.backToTop').remove(); // 拿到混淆後的代碼 => '(function(){}())' let code = Array.from(document.scripts) .find(s => s.innerHTML.search(/window\["\\x65\\x76\\x61\\x6c"\]/) > -1) .innerHTML .slice(26, -1) // 後續的執行中會用到頁面的字串原型擴充方法 String.prototype.splic = unsafeWindow.String.prototype.splic // 拿到執行 SMH.imgData({xxx}) 的代碼,切出漫畫網址的物件資料 ({xxx}) // 前後保留括號,方便下一步 return 物件出來 let imgDataCode = eval(code).slice(11, -11) let imgData = eval(imgDataCode) // servs[pVars.curServ].hosts[pVars.curHost].h let domain = 'https://us.hamreus.com/' // webp // picUrls = imgData.files.map(fileName => domain + imgData.path + fileName + '?e=' + imgData.sl.e + '&m=' + imgData.sl.m) // jpg picUrls = imgData.files.map(fileName => domain + imgData.path + fileName.slice(0, -5) + '?e=' + imgData.sl.e + '&m=' + imgData.sl.m) // function showChapters(){ // $(".result-none").replaceWith(LZString.decompressFromBase64($("#__VIEWSTATE").val())); // $("#__VIEWSTATE").remove(); // } // function chgCountry(){ // document.cookie = "country=HX;domain=.manhuagui.com;path=/;expires=" + (new Date(2100, 0)).toUTCString() + ";"; // } } function comicvip(){ pageNum = unsafeWindow.p; picCount = unsafeWindow.ps; picArea = getEl('#TheImg').parentElement; picUrls = new Array(pageNum-1); pics = new Array(pageNum-1); let su = unsafeWindow.su; let ti = unsafeWindow.ti; let nn = unsafeWindow.nn; let mm = unsafeWindow.mm; let imgurl; for(let s of document.scripts){ imgurl = s.innerHTML.match(/ge\('TheImg'\)\.src *?= *?(.+?;)/); if(imgurl){ imgurl = imgurl[1]; for(let i of s.innerHTML.match(/var +?\w+? *?= *?lc\(/g)){ eval(i.slice(0, -3) + 'unsafeWindow.' + i.match(/var +?(\w+?) *?= *?lc\(/)[1]); } break; } } for(var i=0; i<picCount; i++){ let p = i + 1; picUrls[i] = eval(imgurl); } getEl('#TheImg').remove(); // 新增上下一話按鈕 let prev_button = getEl('#prevvol').cloneNode(true); let next_button = getEl('#nextvol').cloneNode(true); prev_button.removeAttribute('id'); next_button.removeAttribute('id'); let bottom = getEl('#prevnext2'); while (bottom.firstChild) bottom.firstChild.remove(); bottom.appendChild(prev_button); let sp = document.createElement("div") sp.style.display = 'inline-block'; sp.style.width = '6em'; bottom.appendChild(sp); bottom.appendChild(next_button); } function cartoonmad(){ let s = getEl('select'); pageNum = parseInt(s.value.match(/\d+/)[0], 10); picCount = s.options.length - 1; picUrls = new Array(pageNum-1); pics = new Array(pageNum-1); picArea = getEl('body > table:nth-child(1) > tbody:nth-child(1) > tr:nth-child(4) > td'); picArea.style.paddingTop = '30px' let baseUrl = picArea.querySelector('img').src.match(/.+\//)[0] for (let i = 0; i < picCount; i++){ picUrls[i] = baseUrl + (i + 1).toString().padStart(3, '0') } } function gufengmh8() { let chapterImages = clone(unsafeWindow.chapterImages) pageNum = unsafeWindow.SinTheme.getPage() picCount = chapterImages.length pics = Array(pageNum - 1).fill() picArea = getEl('#tbCenter') picArea.classList.remove('tbCenter') picArea.setAttribute('align', 'center'); getEl('#subNav').remove() // SinConf.resHost let domain = unsafeWindow.SinConf.resHost[0].domain[0] picUrls = chapterImages.map(fileName => domain + '/' + unsafeWindow.chapterPath + fileName) } function manhuabei() { let code = (function () { let key = CryptoJS.enc.Utf8.parse('123456781234567G') let iv = CryptoJS.enc.Utf8.parse('ABCDEF1G34123412') let decrypt = CryptoJS.AES.decrypt(chapterImages, key, { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }) let decryptedStr = decrypt.toString(CryptoJS.enc.Utf8) return decryptedStr.toString() }).toString() let chapterImages = JSON.parse(unsafeWindow.eval('(' + code + ')()')) pageNum = unsafeWindow.SinTheme.getPage() picCount = chapterImages.length picArea = getEl('.comic_wraCon') picArea.classList.remove('comic_wraCon') let domain = unsafeWindow.SinConf.resHost[0].domain[0] if (unsafeWindow.chapterPath === '') picUrls = chapterImages else picUrls = chapterImages.map(fileName => domain + '/' + unsafeWindow.chapterPath + fileName) pics = Array(pageNum - 1).fill() getEl('#mainNavDl').remove() getEl('.side_bar').remove() getEl('#sidePublic').remove() } document.documentElement.style.overflowY = 'scroll'; var isLog = false var viewport = (document.compatMode == 'BackCompat') ? document.body : document.documentElement; var zoomScreen = (() => { let isWebKit = navigator.userAgent.indexOf('WebKit') > -1 return { width: isWebKit ? screen.width / devicePixelRatio : screen.width, height: isWebKit ? screen.height / devicePixelRatio : screen.height, } })() var min_h_width = Math.round(zoomScreen.width * 0.7) var max_h_width = Math.round(zoomScreen.width - (26 / devicePixelRatio)) var min_v_height = Math.round(zoomScreen.height * 1.25) var max_v_height = Math.round(zoomScreen.height * 1.3) var preCount = 5; var overRange = zoomScreen.height * 2; var pageNum; var picCount; var picArea; var picUrls; var pics; switch(location.hostname){ case 'www.dm5.com': case 'www.1kkk.com': // manhuaren(); dm5() break; case 'exhentai.org': case 'e-hentai.org': eh(); break; case 'comicbus.com': case 'comicbus.live': comicvip(); break; case 'www.manhuagui.com': case 'tw.manhuagui.com': manhuagui(); break; case 'www.cartoonmad.cc': cartoonmad(); break; case 'www.gufengmh8.com': case 'www.36mh.com': case 'www.90mh.com': gufengmh8(); break case 'www.manhuabei.com': case 'www.manhuafen.com': manhuabei(); break } picArea.innerHTML = ''; preload(); showPics(); preload(); (function(){ log('onscroll'); if(picArea.scrollHeight > 1000){ log('onscroll start'); onscroll = function(){ if(picArea.offset().bottom-viewport.scrollTop < overRange){ log('scrollTop: ' + viewport.scrollTop + '\npicArea.bottom: ' + picArea.offset().bottom); showPics(); preload(); if(pageNum>picCount){ log('onscroll stop, pageNum: ' + pageNum); onscroll = undefined; } } }; }else if(pageNum<=picCount){ setTimeout(arguments.callee, 500); } })();