您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
使用左右方向键来翻页 [Ver 0.1.7.4+]
// ==UserScript== // @name Next Page-bobo3 // @author Sunwan,bobo // @version 0.2.7.3.005-bobo3 // @namespace https://greasyfork.org/zh-CN/scripts/510005-next-page-bobo3/code // @description 使用左右方向键来翻页 [Ver 0.1.7.4+] // @grant GM_getValue // @grant GM_setValue // @grant GM_registerMenuCommand // @license MIT License // @include http://* // @include https://* // ==/UserScript== (function() { var checked = false; var delay = false; var next = {}; var previous = {}; var but1 =false; var but2 =false; // 下一页链接里的文字 //包含,一、页、頁、翻,的链接text,才进入详细比对 next.texts = ['下页', '下頁', '下一页', '下一頁', '后一页', '后一頁', '翻下页', '翻下頁', '后页', '后頁', '下翻', '下一个', '下一张', '下一幅', '下一节', '下一章', '下一章 →', '下一篇', '后一章', '后一篇' ]; // 上一页链接里的文字 previous.texts = ['上页', '上頁', '上一页', '上一頁', '前一页', '前一頁', '翻上页', '翻上頁', '前页', '前頁', '上翻', '上一个', '上一张', '上一幅', '上一节', '上一章', '← 上一章', '上一篇', '前一章', '前一篇' ]; // 可能会误判的关键词 next.miswords = { "x下一章": 30, "下一篇": 30, "后一章": 30, "后一篇": 30, "下一节": 30, ">>": 2000, "?": 2000 }; previous.miswords = { "x上一章": 30, "上一篇": 30, "前一章": 30, "前一篇": 30, "上一节": 30, "<<": 2000, "?": 2000 }; // 注册脚本菜单 registerMenu("next"); registerMenu("previous"); // 取得自定义关键词 getCustom(next, "next"); getCustom(previous, "previous"); // 最后添加一些论坛使用的翻页符号 next.texts.push(">>"); next.texts.push(">"); previous.texts.push("<<"); previous.texts.push("<"); // 翻页文字的前面和后面可能包含的字符(正则表达式) var preRegexp = '(^\\s*(?:[<??]*|[>??]*|[\\(\\[『「[【]?)\\s*)'; var nextRegexp = '(\\s*(?:[>??]*|[\\)\\]』」]】]?)\\s*$)'; /* 假函数防止其他js监控键盘 function jumpPage111(ee1){} document.onkeydown = jumpPage111; */ //等页面加载完成执行下一页扫描 document.onreadystatechange = function() //当页面加载状态改变的时候执行function { if(document.readyState == "complete") { //当页面加载状态为完全结束时进入 //document.getElementById("content").style.fontSize ="34px"; console.error("页面加载完执行init112,ddddddddddddd"); //alert("dddddddddd"); init112(); //你要做的操作。 } } function init113(){ let els = document.getElementsByClassName('muye-reader-inner'); // els[0].style.width = "1800px"; //els[0].style.max-width = "1800px"; els[0].style.cssText = "width:1450px;max-width:1450px;"; console.error("页面加载完执行 els[0].style.width = '1450';"); console.error(els); let els2 = document.getElementsByClassName('reader-toolbar'); els2[0].style.cssText ="right: 50px;"; console.error("页面加载完执行els2[0].style.cssText =='right: 30px;';"); console.error(els2); } function init112(){ if (!checked) { checkLinks(); checked = true; } //init113(); } // 取得并设置自定义关键词 function getCustom(aObj, key) { var site, re; var cKeyWords = GM_getValue("custom_" + key, ""); var words = cKeyWords.split(/,|,/); for (var w in words) { site = null; if (/^\s*{\s*(\S*?)\s*}(.*)$/.test(w)) { site = RegExp.$1; w = RegExp.$2; site = site.replace(/[\/\?\.\(\)\+\-\[\]\$]/g, "\\$&").replace(/\*/g, "\.*"); } w = w.replace(/\\/g, "\\").replace(/^\s+|\s+$/g, ""); if (w) { if (site) { re = eval('/' + site + '/i'); if (re.test(location.href)) aObj.texts.push(w); } else aObj.texts.push(w); } } } // 注册菜单 function registerMenu(key) { if (navigator.language == "zh-CN") { var word = key == "next" ? "下一页" : "上一页"; GM_registerMenuCommand("Next Page " + word + "关键词", function(){setCustom(key, word);}); } else { GM_registerMenuCommand("Next Page custom_" + key, function(){setCustom(key, key);}); } } // 设置新的关键词 function setCustom(k, w) { var text = navigator.language == "zh-CN" ? "请输入“"+w+"”的关键词,以“,”号分隔开。" : "Please enter the "+w+" page key-words, split with ','."; var result = prompt(text, GM_getValue("custom_" + k, "")); if (result != null) GM_setValue("custom_" + k, result); } function checkLinks() { var link, text, ldnc, lnc, ldpc, lpc, num, digCurFound, linkNumber, found, tmpNode; var regexp = new RegExp(); // 查找相应的链接 var links = document.getElementsByTagName('A'); for (var i = links.length-1; i >=0; i--) { //倒序查找速度更快 link = links[i]; // 跳过不起作用的链接 if (!link.offsetParent || link.offsetWidth == 0 || link.offsetHeight == 0 || !link.hasAttribute("href") && !link.hasAttribute("onclick")) continue; // 跳过日历 if (/(?:^|\s)(?:monthlink|weekday|day|day[\-_]\S+)(?:\s|$)/i.test(link.className)) continue; if (/^nextlink/i.test(link.id) || /^linknext/i.test(link.id) || /(^|\s)nextlink/i.test(link.className) || /(^|\s)linknext/i.test(link.className)) next.link = link; if (/^prev(ious)?link/i.test(link.id) || /^linkprev(ious)?/i.test(link.id) || /(^|\s)prev(ious)?link/i.test(link.className) || /(^|\s)linkprev(ious)?/i.test(link.className)) previous.link = link; text = link.textContent; if (!text) { // 若链接中没有文字,则检查图片的alt属性、链接或图片的title for (var img in link.childNodes) { if (img.localName == "IMG") { text = img.alt || link.title || img.title; if (text) break; } } if (!text) continue; } text = text.toLowerCase().replace(/^\s+|\s+$/g, ""); if (!text) continue; // 纯数字链接 if (isDigital(text)) { if (digCurFound) continue; linkNumber = parseInt(RegExp.$1); // 检测下一个位置是否是当前页面的页数 if ((tmpNode = getCurrentPageNode(link, linkNumber, 1)) && tmpNode) { digCurFound = true; previous.link = link; previous.found = true; previous.pos = i; // 再检测下下一个位置是否是“下一页”的链接 if (getNextLink(tmpNode, linkNumber+2, true)) break; // 设置往后的30个位置以内为“下一页”的可能链接,以提高检测速度。 ldnc = i + 30; } // 检测上一个位置是否是当前页面的页数 else if (getCurrentPageNode(link, linkNumber, -1)) { digCurFound = true; next.link = link; next.found = true; next.pos = i; ldpc = i + 30; continue; } // 检测自身是否是当前页面的页数 else if (getCurrentPageNode(link, linkNumber, 0)) { digCurFound = true; // 再检测下一个位置是否是“下一页”的链接 if (getNextLink(link, linkNumber+1, true)) { next.pos = i; ldpc = i + 30; continue; } // 设置往后的30个位置以内为“下一页”的可能链接,以提高检测速度。 ldnc = i + 30; } continue; } else { found = false; //包含,一、页、頁、翻,的链接text,才进入详细比对 var xxxx1=regexp.compile( '一|页|頁|翻', 'i').test(text); if (xxxx1){ //详细比较 if (!next.found && !(lnc < i) && !(ldnc < i)) { for (var j = 0; j < next.texts.length; j++) { if (regexp.compile(preRegexp + next.texts[j] + nextRegexp, 'i').test(text)) { // 检测到“下一页”的链接 found = true; next.link = link; num = next.miswords[next.texts[j]]; // 若“下一页”的词语有可能会误判时,最多再检测预定个数的链接。 var vv1 = (num == null) ? next.found = true : lnc = i + num; break; } } } if (!next.digital && lnc < i) next.found = true; if (!found && !previous.found && !(lpc < i) && !(ldpc < i)) { for (var j3 = 0; j3< previous.texts.length; j3++) { if (regexp.compile(preRegexp + previous.texts[j3] + nextRegexp, 'i').test(text)) { // 检测到“上一页”的链接 previous.link = link; num = previous.miswords[previous.texts[j3]]; // 若“上一页”的词语有可能会误判时,最多再检测预定个数的链接。 var vv2 = (num == null) ? previous.found = true : lpc = i + num; break; } } } if (lpc < i) previous.found = true; // 重新设置纯数字链接未被检查 digCurFound = null; } } // 找到“上一页”和“下一页”的链接或找到其中一个而另一个超过规定范围没找到,将不再查找。 if (next.found && previous.found || next.found && i > next.pos + 40 || previous.found && i > previous.pos + 40) break; } // 通过以上方法没有找到“下一页”的,把第一次检测出来的数字1的链接作为当前页,2作为“下一页”。 if (!next.found /*&& !next.link*/ && next.digital) next.link = next.digital; if (next.link) next.found = true; if (previous.link) previous.found = true; if (!next.found && !previous.found) { console.error("将要执行checkButtons()"); checkButtons(); } } // 检查翻页按钮 function checkButtons() { var but, text, found; var regexp = new RegExp(); var buts = document.getElementsByTagName('button'); for (var i = 0; i < buts.length; i++) { but = buts[i]; /* 综上所述,这段代码的作用是检查按钮是否被禁用、是否是一个标准的按钮类型 (<button type="button">) 以及是否定义了点击事件处理函数。如果按钮不符合这些条件,则跳过这次循环迭代,继续检查下一个按钮。 */ //原版continue跳出for if (but.hasAttribute("disabled") || !(/^button$/i.test(but.type) && but.getAttribute("onclick"))) continue; if (but.hasAttribute("disabled") || !(/^button$/i.test(but.type) )) continue; text = but.textContent; found = false; //console.error(text); console.error(" 开始检测到下一页的按钮"); if (!next.found) { for (var j = 0; j < next.texts.length; j++) { if (regexp.compile(preRegexp + next.texts[j] + nextRegexp, 'i').test(text)) { // 检测到“下一页”的按钮 console.error(" 检测到“下一页”的按钮,"+ text ); but2 = but; next.found = found = true; break; } } } if (!previous.found) { for (var j2 = 0; j2 < previous.texts.length; j2++) { if (regexp.compile(preRegexp + previous.texts[j2] + nextRegexp, 'i').test(text)) { // 检测到“上一页”的按钮 console.error(" 检测到“上一页”的按钮,"+ text ); but1 = but; previous.found = true; break; } } } if (next.found && previous.found) break; } } // 取得相邻的纯数字节点,type: 1 下一个;-1 上一个 function getSiblingNode(node, type) { if (!node) return null; node = getSibling(node, type); while (node && (node.nodeName == "#coment" || (/^\s*[\]]】]?[,\|]?\s*[\[[【]?\s*$/.test(node.textContent)))) node = getSibling(node, type); return node; } function getSibling(aNode, type) { if (!aNode) return null; if (isOnlyNode(aNode)) { try { aNode = (type == 1 ? aNode.parentNode.nextSibling : aNode.parentNode.previousSibling); if (skipNode(aNode)) aNode = (type == 1 ? aNode.nextSibling : aNode.previousSibling); aNode = aNode.childNodes[0]; if (skipNode(aNode)) aNode = aNode.nextSibling; } catch (e) {return null;} } else { aNode = (type == 1 ? aNode.nextSibling : aNode.previousSibling); } return aNode; } function isOnlyNode(n) { return !n.nextSibling && !n.previousSibling || !n.nextSibling && skipNode(n.previousSibling) && !n.previousSibling.previousSibling || !n.previousSibling && skipNode(n.nextSibling) && !n.nextSibling.nextSibling || skipNode(n.previousSibling) && !n.previousSibling.previousSibling && skipNode(n.nextSibling) && !n.nextSibling.nextSibling; } function skipNode(sNode) { return sNode && /*sNode.nodeName == "#text" &&*/ (/^\s*$/.test(sNode.textContent)); } // 检测是否有下一页的纯数字链接,number:页数 function getNextLink(node, number, set) { var tNode = getSiblingNode(node, 1); if (tNode && tNode.nodeName == "A" && isDigital(tNode.textContent)) { if (RegExp.$1 == number) { // 找到纯数字链接 if (set) { next.link = tNode; next.found = true; } return tNode; } } return null; } function isDigital(str, t) { str = str.replace(/^\s+|\s+$/g, ""); if (t == -1) str = str.split(/\s+/).pop(); else if (t == 1) str = str.split(/\s+/)[0]; return (/^(\d+)$/.test(str)) || (/^\[\s?(\d+)\s?\]$/.test(str)) || (/^【\s?(\d+)\s?】$/.test(str)) || (/^[\s?(\d+)\s?]$/.test(str)) || (/^<\s?(\d+)\s?>$/.test(str)); } // 判断是否是当前页面的数字,type:-1,0,1 分别是要判别的上一个、当前、下一个节点 function getCurrentPageNode(node, linkNum, type) { var tNode; if (type == 0) { tNode = getSiblingNode(node, 1) || getSiblingNode(node, -1); if (!tNode) return null; if (!node.hasAttribute("onclick") && node.href != tNode.href && (!node.hasAttribute("href") && isDigital(node.textContent, type) || !(/\/#[^\/]+$/.test(node.href)) && node.href == location.href && isDigital(node.textContent, type))) { if (linkNum > 0 && RegExp.$1 == linkNum) return node; } // 某些论坛处在第一页时,实际链接和当前页链接不符,只有和其余纯数字链接的结构或颜色不同时, // 才使用纯数字的“2”作为“下一页”的链接。 else if (!next.digital && (/^\s*[\[[【]?1[\]]】]?\s*$/.test(node.textContent))) { var two = getNextLink(node, 2); if (two && difDigital(node, two)) next.digital = two; } } else { tNode = getSiblingNode(node, type); if (!tNode) return null; if (tNode.nodeName != "A" && isDigital(tNode.textContent, type) || tNode.nodeName == "A" && !tNode.hasAttribute("onclick") && node.href != tNode.href && (!tNode.hasAttribute("href") && isDigital(tNode.textContent, type) || !(/\/#[^\/]+$/.test(tNode.href)) && tNode.href == location.href && isDigital(tNode.textContent, type))) { var n = linkNum + type; if (n > 0 && RegExp.$1 == n) { if (next.digital) next.digital = null; return tNode; } } } return null; } function difDigital(node1, node2) { if (getStructure(node1) == getStructure(node2) && getStyleColor(node1) == getStyleColor(node2)) return false; return true; } function getStructure(aNode) { return aNode.innerHTML.replace(/\d+/, ""); } function getStyleColor(aNode) { return document.defaultView.getComputedStyle(aNode, null).getPropertyValue("color"); } function openLink(linkNode) { if (!linkNode) return; var hf = linkNode.getAttribute("href"); if (!linkNode.hasAttribute("onclick") && hf && !(/^#/.test(hf)) && linkNode.href != location.href) { cleanVars(); location.assign(linkNode.href); } else { // 有些4D鼠标摆动一下滚轮会触发多下的方向键,故增设一个延迟参数,使它只翻一页。 delay = true; setTimeout(cleanVars, 300); var e = document.createEvent("MouseEvents"); e.initMouseEvent("click", 1, 1, window, 1, 0,0,0,0,0,0,0,0,0, linkNode); linkNode.dispatchEvent(e); } } function cleanVars() { try { checked = false; delay = false; next.link = next.found = next.digital = null; previous.link = previous.found = previous.digital = null; delete next.pos; delete previous.pos; } catch(e) {} } function onKeyDown(event) { // 不是左右方向建被按下或不到延迟时间则退出 if (event.ctrlKey || event.shiftKey || event.altKey || event.metaKey ||event.keyCode != 38 &&event.keyCode != 40 && event.keyCode != 37 && event.keyCode != 39 || delay)return; // 确保光标不是定位在文字输入框或选择框 var localName = event.target.localName.toUpperCase(); if (localName == 'TEXTAREA' || localName == 'INPUT' || localName == 'SELECT' || localName == 'DIV')return; // 检查过且没有发现上一页或下一页的连接,则退出 if (checked && !next.found && !previous.found) return; if (!checked) { checkLinks(); checked = true; } /* if (event.keyCode == 40) { init113(); console.error(" 按键下箭头," ); } */ if (event.keyCode == 37 && previous.found) { // 左方向键,跳到“上一页” openLink(previous.link); if (but1){ console.error(" 按钮上一页," ); var event2 = new MouseEvent('click', { bubbles: true, cancelable: true, // view: window }); but1.dispatchEvent(event2); } } else if (event.keyCode == 39 && next.found) { // 右方向键,跳到“下一页” openLink(next.link); if (but2){ console.error(" 按钮下一页," ); var event1 = new MouseEvent('click', { bubbles: true, cancelable: true, // view: window }); but2.dispatchEvent(event1); } } } window.addEventListener("keydown", function(e){onKeyDown(e);}, true); document.onkeydown =onKeyDown; })();