您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
用于binb阅读器v016112版本的小说漫画的获取脚本
// ==UserScript== // @name BinB阅读器捕获脚本(v016112) // @namespace summer-script // @version 0.5.1 // @description 用于binb阅读器v016112版本的小说漫画的获取脚本 // @author summer // @match https://r.binb.jp/epm/* // @grant none // @run-at document-end // ==/UserScript== (function() { 'use strict'; var api = { cid: '', token: '', key: '', contentServer: null, tbl: null, ttx: null, viewMode: 1, isdirect: 0, init: function(cid, cb) { var api = this; api.cid = cid; api.getTbl(function(tbl) { api.tbl = tbl; api.getTTX(function(ttx){ api.ttx = ttx; cb && cb(); }); }); }, getImageUrl: function(path) { var url = this.contentServer + 'sbcGetImg.php' var data = { cid: this.cid, src: path, q: this.key, // vm: this.viewMode }; var qs = this.buildQuery(data); return url + '?' + qs; }, getTbl: function(cb) { if (null !== this.tbl) { return this.tbl; } // var path = 'swsapi/bibGetCntntInfo'; var path = '/~/bibGetCntntInfo'; var token = this._getRandKey(); var api = this; var data = { cid: this.cid, k: token, dmytime: (new Date()).getTime() }; this.token = token; this.jsonGet(path, data, function(ret) { if (!ret || 1 !== parseInt(ret.result)) { cb && cb(false); return; } var item = ret.items[0]; api.key = item.p; api.contentServer = item.ContentsServer; api.viewMode = item.ViewMode; api.isdirect = (1 === item.ServerType); var tbl = { stbl: api._decodeTbl(api.cid, token, item.stbl), ttbl: api._decodeTbl(api.cid, token, item.ttbl), ctbl: api._decodeTbl(api.cid, token, item.ctbl), ptbl: api._decodeTbl(api.cid, token, item.ptbl), }; cb && cb(tbl); }); }, getTTX: function(cb) { if (null !== this.ttx) { return this.ttx; } var api = this; if (null === this.contentServer) { this.getTbl(function() { api.getTTX(cb); }); return; } var path = this.contentServer + 'sbcGetCntnt.php'; var data = { cid: this.cid, p: this.key, dmytime: (new Date()).getTime() }; this.jsonGet(path, data, function(ret) { if (!ret || 1 !== parseInt(ret.result)) { cb && cb(false); return; } cb(ret.ttx); }); }, buildQuery: function(obj) { var str = []; for (var p in obj) { if (obj.hasOwnProperty(p)) { str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p])); } } return str.join("&"); }, jsonGet: function(path, data, cb) { if ('function' === typeof(data)) { cb = data; } else if ('object' === typeof(data)) { path += '?' + this.buildQuery(data); } else if ('string') { path += data; } var xhr = new XMLHttpRequest(); xhr.onreadystatechange = function() { if (XMLHttpRequest.DONE === xhr.readyState) { var ret; if (200 === xhr.status) { try { ret = JSON.parse(xhr.responseText); } catch(err) { ret = false; } cb(ret); } } }; xhr.open('GET', path); xhr.send(); }, _getRandKey: function() { var cid = this.cid; var n = this._getRandomString(16) , i = Array(Math.ceil(16 / cid.length) + 1).join(cid) , r = i.substr(0, 16) , e = i.substr(-16, 16) , s = 0 , u = 0 , h = 0; return n.split("").map(function(t, i) { var keys = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'; return s ^= n.charCodeAt(i), u ^= r.charCodeAt(i), h ^= e.charCodeAt(i), t + keys[s + u + h & 63] }).join("") }, _decodeTbl: function(cid, token, data) { for (var r = cid + ":" + token, e = 0, s = 0; s < r.length; s++) { e += r.charCodeAt(s) << s % 16; } 0 == (e &= 2147483647) && (e = 305419896); var u = "" , h = e; for (s = 0; s < data.length; s++) { h = h >>> 1 ^ 1210056708 & -(1 & h); var o = (data.charCodeAt(s) - 32 + h) % 94 + 32; u += String.fromCharCode(o) } try { return JSON.parse(u) } catch (t) { return false } }, _getRandomString: function(leng, i) { var keys = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'; for (var n = i || keys, r = (n.length, ""), e = 0; e < leng; e++) r += n.charAt(Math.floor(Math.random() * n.length)); return r } }; var reader = { ptbl: '', ctbl: '', stbl: '', ttbl: '', total: 0, button: null, decoder: null, init: function(decoder) { this.decoder = decoder; return this; }, isSupport: function() { var verSupport = ['v016112', '1.6112.5484', '01.6112']; var verNow = this.getReaderVer(); if (!verNow) { return false; } return (-1 !== verSupport.indexOf(verNow.toString())); }, isComicReader: function() { if (undefined !== window.CURRENT_VERSION) { return false; } if (undefined !== window.Z6K1XZ) { return false; } return true; }, getFrameUrl: function() { if (undefined === window.BINB_READER_URL) { return false; } var base = window.BINB_READER_URL; var ver = this.getReaderVer(); var orgn = location.protocol + '//' + location.hostname + '/'; cid = encodeURIComponent(cid); ver = encodeURIComponent(ver); orgn = encodeURIComponent(orgn); var url = base + '&ver=' + ver + '&cid=' + cid + '&msgorgn=' + orgn; return url; }, getCid: function() { if (document.getElementById('binb_cid')) { return document.getElementById('binb_cid').value; } else if (undefined !== this._getUrlParam('cid')) { return this._getUrlParam('cid'); } return false; }, getReaderVer: function() { return window.CURRENT_VERSION || window.ViewerVersion || ''; }, loadImg: function(ttx, cb) { var reader = this; var queue = ttx; if ('string' === typeof(queue)) { // TODO decode queue = ('comic' === this.mode) ? this.decoder.decodeComicTTX(ttx) : this.decoder.decodeNovelTTX(ttx); reader.total = queue.length; } if (0 === queue.length) { return; } var path = queue.shift(); var sum = this.total; var now = sum - queue.length; var img = new Image(); img.onerror = function() { console.log('image['+now+'] load fail, retrying...'); img.onload = undefined; queue.unshift(path); setTimeout(function() { reader.loadImg(queue, cb); }, 2000); }; img.onload = function() { cb(img, path, now, sum); reader.loadImg(queue, cb); }; img.src = api.getImageUrl(path); }, draw: function(img, imgPath) { var coords = this.decoder.calcCoords(imgPath, img.width, img.height); var size = this.decoder.getImgOrgSize(img.width, img.height); var cv = document.createElement('canvas'); cv.width = size.width; cv.height = size.height; var ctx = cv.getContext('2d'); for(var i in coords) { ctx.drawImage( img, coords[i].xsrc, coords[i].ysrc, coords[i].width, coords[i].height, coords[i].xdest, coords[i].ydest, coords[i].width, coords[i].height ); } return cv; }, download: function(canvas, filename) { canvas.toBlob(function(blob) { var url = URL.createObjectURL(blob); var a = document.createElement('a'); a.download = filename; a.href = url; a.click(); }); }, _getUrlParam: function(key) { var search = location.search.substring(1); var obj = search.split("&").reduce(function(prev, curr) { var p = curr.split("="); if (undefined === p[1]) { p[1] = ''; } prev[decodeURIComponent(p[0])] = decodeURIComponent(p[1]); return prev; }, {}); return obj[key]; } }; var decoder = { init: function(tbl) { if (!tbl.ptbl || !tbl.ctbl || !tbl.stbl || !tbl.ttbl) { return false; } this.ptbl = tbl.ptbl; this.ctbl = tbl.ctbl; this.stbl = tbl.stbl; this.ttbl = tbl.ttbl; return true; }, calcCoords: function(imgPath, width, height) { this._decodeTbl(imgPath); var t = {width: width, height, height}; if (null === this.jt) return false; if (!this._valiImgSize(t)) { return [{ xsrc: 0, ysrc: 0, width: t.width, height: t.height, xdest: 0, ydest: 0 }]; } var i = t.width - 2 * this.A * this.Et, n = t.height - 2 * this.I * this.Et, r = Math.floor((i + this.A - 1) / this.A), e = i - (this.A - 1) * r, s = Math.floor((n + this.I - 1) / this.I), u = n - (this.I - 1) * s, h = []; for (var o = 0; o < this.A * this.I; ++o) { var a = o % this.A , c = Math.floor(o / this.A) , f = this.Et + a * (r + 2 * this.Et) + (this.Tt[c] < a ? e - r : 0) , l = this.Et + c * (s + 2 * this.Et) + (this.Pt[a] < c ? u - s : 0) , v = this.jt[o] % this.A , d = Math.floor(this.jt[o] / this.A) , p = v * r + (this.It[d] < v ? e - r : 0) , g = d * s + (this.St[v] < d ? u - s : 0) , b = this.Tt[c] === a ? e : r , m = this.Pt[a] === c ? u : s; 0 < i && 0 < n && h.push({ xsrc: f, ysrc: l, width: b, height: m, xdest: p, ydest: g }) } return h }, decodeComicTTX: function(ttx) { var start = ttx.indexOf('t-case') - 1; var end = ttx.indexOf('/t-case') + 8; var ttxContent = ttx.substring(start, end); var imgttx = ttxContent.match(/<t-img.+?>/g); var content = []; for (var i = 0; i < imgttx.length; i++) { var src = /src="(.+?)"/.exec(imgttx[i])[1]; content.push(src); } return content; }, decodeNovelTTX: function(ttx) { var imgttx = ttx.match(/<t-img.+?>/g); var content = []; for (var i = 0; i < imgttx.length; i++) { var src = /src="(.+?)"/.exec(imgttx[i])[1]; content.push(src); } return this._arrUnique(content); }, getImgOrgSize: function(width, height) { var t = {width: width, height: height}; return this._valiImgSize(t) ? { width: t.width - 2 * this.A * this.Et, height: t.height - 2 * this.I * this.Et } : t; }, _decodeTbl: function (imgPath) { var i = [0, 0]; if (imgPath) { for (var n = imgPath.lastIndexOf("/") + 1, r = imgPath.length - n, e = 0; e < r; e++) i[e % 2] += imgPath.charCodeAt(e + n); i[0] %= 8, i[1] %= 8 } var t = this.ctbl[i[1]]; i = this.ptbl[i[0]]; n = t.match(/^=([0-9]+)-([0-9]+)([-+])([0-9]+)-([-_0-9A-Za-z]+)$/) , r = i.match(/^=([0-9]+)-([0-9]+)([-+])([0-9]+)-([-_0-9A-Za-z]+)$/); this.jt = null; this.A = parseInt(n[1], 10); this.I = parseInt(n[2], 10); this.Et = parseInt(n[4], 10); if (null !== n && null !== r && n[1] === r[1] && n[2] === r[2] && n[4] === r[4] && "+" === n[3] && "-" === r[3] && (!(8 < this.A || 8 < this.I || 64 < this.A * this.I))) { e = this.A + this.I + this.A * this.I; if (n[5].length === e && r[5].length === e) { var s = this._decodeTblKey(n[5]) , u = this._decodeTblKey(r[5]); this.It = s.n, this.St = s.t, this.Tt = u.n, this.Pt = u.t, this.jt = []; for (var h = 0; h < this.A * this.I; h++) this.jt.push(s.p[u.p[h]]) } } }, _decodeTblKey: function(t) { var key = [ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 ]; var i, n = [], r = [], e = []; for (i = 0; i < this.A; i++) n.push(key[t.charCodeAt(i)]); for (i = 0; i < this.I; i++) r.push(key[t.charCodeAt(this.A + i)]); for (i = 0; i < this.A * this.I; i++) e.push(key[t.charCodeAt(this.A + this.I + i)]); return { t: n, n: r, p: e } }, _valiImgSize: function(t) { var i = 2 * this.A * this.Et , n = 2 * this.I * this.Et; return t.width >= 64 + i && t.height >= 64 + n && t.width * t.height >= (320 + i) * (320 + n) }, _arrUnique: function(arr) { var val; var map = {}; var output = []; for (var i = 0; i < arr.length; i++) { val = arr[i]; if (undefined === map[val]) { map[val] = true; output.push(val); } } return output; } }; var screenshoter = { counter: 0, hook: null, init: function() { var func = window.ZXA0CC; var sser = this; this.counter = 0; window.ZXA0CC = function() { func(); var cvid = window.Z9C0HY[window.Z7K02M]; var cv1 = document.getElementById(cvid); sser.counter++; sser.hook && sser.hook(cv1, sser.counter); }; return this; }, catch: function(cb) { this.hook = cb; }, reset: function() { window.Z5H0CK(0, false); }, next: function() { window.ZKT0I2(); }, ending: function() { var clast = window.ZHL0PP.ZI50JA() - 1; var last1 = !(window.ZQH0T9 < clast); var last2_1 = window.ZQH0T9 == clast; var last2_2 = false === window.ZHL0PP.Z060JL(); var last2 = !(last2_1 && last2_2); return last1 && last2; } }; var btn = { button: [], wrap: null, init: function() { this._createWrap(); return this; }, add: function(text) { var btn = this._createBtn(); btn.innerText = text; this.button.push(btn); return new this._instance(btn); }, _instance: function(btn) { this.button = btn; this.tip = function(text, add) { if (add) { text = this.button.innerText + text; } this.button.innerText = text; return this; }; this.disable = function() { this.button.disabled = true; return this; }; this.enable = function() { this.button.disabled = true; return this; }; this.hide = function() { this.button.style.display = 'none'; return this; }; this.show = function() { this.button.style.display = 'block'; return this; }; this.onclick = function(cb) { var thisBtn = this; this.button.addEventListener('click', function() { cb(thisBtn) }); return this; }; }, _createWrap: function() { var wrap = document.createElement('div'); wrap.style.top = '6px'; wrap.style.right = '8px'; wrap.style.zIndex = '302'; wrap.style.position = 'fixed'; document.body.appendChild(wrap); this.wrap = wrap; }, _createBtn: function() { var btn = document.createElement('button'); btn.style.marginLeft = '8px'; btn.style.padding = '8px'; btn.style.background = '#fff'; btn.style.border = '1px solid #aaa'; btn.style.borderRadius = '4px'; btn.style.minWidth = '112px'; btn.style.color = '#000'; btn.style.float = 'right' this.wrap.appendChild(btn); return btn; } }; reader.init(decoder); btn.init(); var btn1 = btn.add('正在初始化...'); var btn2 = btn.add('正在初始化...'); btn2.hide(); var cid = reader.getCid(); if (!cid) { btn1.tip('脚本暂不支持当前作品'); return; } var jump = reader.getFrameUrl(); if (jump) { btn1.tip('正在跳转...'); window.location.href = jump; return; } api.init(cid, function() { var tbl = api.getTbl(); var init_d = decoder.init(tbl); if (!init_d) { btn1.tip('初始化失败'); return; } if (!reader.isSupport()) { btn.add('(脚本暂不支持当前作品, 无法保证能正常运行)'); } if (reader.isComicReader()) { btn1.tip('开始捕获'); } else { btn1.tip('提取插图'); btn2.tip('自动截图').show(); } btn1.onclick(_getFromTTX); btn2.onclick(_getFromCanvas); }); function _getFromTTX(btn) { btn.disable(); btn.tip('正在运行...'); var ttx = api.getTTX(); reader.loadImg(ttx, function(img, path, now, sum) { var canvas = reader.draw(img, path); var prefix = document.title; var filename = prefix + '-img-' + now + '.png'; reader.download(canvas, filename); btn.tip('正在运行...('+now+'/'+sum+')'); if (now >= sum) { btn.tip('运行完毕'); } }); } function _getFromCanvas(btn) { btn.disable(); btn.tip('正在运行...'); screenshoter.init(); screenshoter.catch(function(canvas, now) { btn.tip('正在运行...(第'+now+'页)'); var prefix = document.title; var filename = prefix + '-screenshot-' + now + '.png'; reader.download(canvas, filename); if (screenshoter.ending()) { btn.tip('截图完毕'); return; } screenshoter.next(); }); screenshoter.reset(); } })();