// ==UserScript== // @name 起点小说vip自动换源 // @namespace http://tampermonkey.net/ // @version 2.0 // @description 对起点的vip小说自动搜索笔趣阁,要设置滚动模式,自动加载形式,支持手机和网页 // @author JucyZhu // @match https://m.qidian.com/book/* // @match https://read.qidian.com/chapter/* // @match https://vipreader.qidian.com/chapter/* // @require https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js // @connect www.xbiquge.la // @connect m.xbiquge.la // @connect so.biqusoso.com // @connect www.20xs.cc // @connect www.lvsetxt.com // @run-at document-end // @grant GM_xmlhttpRequest // @downloadURL none // ==/UserScript== (function() { 'use strict'; // Your code here... // 声明全局参数 // ===== 自定义站点规则 ===== const sites = [ // 详细版规则示例。注:该网站已无法访问。 { //基本信息 siteName: "新笔趣阁", // 站点名字... (可选) URL: "http://www.xbiquge.la", searchURL: "http://www.xbiquge.la/modules/article/waps.php", //搜索相关 method: "POST", //请求方式 formData: "searchkey=", //请求数据 needName: false, bookName: "tbody tr .even a", //解析搜索结果相关 authorName: "tbody tr .even:odd", chapters: "#list dl a", //解析目录列表相关 contentSplit: "\n\n", //章节分段方式 content: "#content", //解析章节内容 replace: "#content p", }, { //基本信息 siteName: "新笔趣云", URL: "https://www.20xs.cc", searchURL: "https://www.20xs.cc/searchbook.php?search_key=", method: "GET", formData: "search_key=", needName: true, bookName: "strong a", authorName: "#li1 .name span:odd", chapters: "#list dl a", contentSplit: "node", //章节分段方式 content: "#content p", replace: "", } ]; var data = { book: {}, currentChapter: {}, chapters: [], isApp: false }, chapterNum = 0, first_time = true, lock = true, siteId = 0, show = false; //脚本更新data获取书籍信息 getBookContents(); //滚动事件 $(window).scroll(function() { if (data.isApp) { show = ($(".read-article .read-section").last().offset().top - $(document).scrollTop() < $( window).height()); } else { show = ($("#j_chapterBox .text-wrap:last").offset().top - $(document).scrollTop() < $(window) .height()); } if (($(window).scrollTop() * 1.05 > $(document).height() - $(window).height()) && show && lock) { lock = false; loadbook(); } }); function loadbook() { updata(); //更新data if (chapterNum > 3) { if (data.isApp) { $(".read-section").first().remove() chapterNum = $(".read-section").length } else { $(".text-wrap").first().remove() chapterNum = $(".text-wrap").length } } if (data.currentChapter.vipState == 1 && chapterNum <= 3) { updataCurrentChapter(data.currentChapter.id + 1) console.log(data.currentChapter) insertCurrentVipContents(); } }; //根据当前章节名称,如果是vip则从笔趣阁获取内容资源并插入 function insertCurrentVipContents() { //根据找到的当前章节url获取说内容并解析 console.log("------正在请求《" + data.currentChapter.chapterName + "》的内容------") var href = data.currentChapter.href; GM_xmlhttpRequest({ method: "GET", url: href, headers: { "Content-Type": "application/x-www-form-urlencoded;charset=utf-8" }, data: "", onload: function(response) { //console.log("请求成功"); insertChapter(parseContent(response.responseText)) }, onerror: function(response) { console.log("请求失败: href: " + href); } }) }; //更新vip状态和显示章节数 function updata() { //有没有到vipstate==0 &&(登录按钮,订阅按钮长度大于0(有.btn-primary) //或者.j_subscribeBtn vip章节全部订阅和订阅本章按钮长度大于0 //或者发现.w-all前往vip章节长度大于0) if (data.currentChapter.vipState == 0) { if ($(".btn-primary").length > 0) { //手机版 data.currentChapter.vipState = 1; $(".btn-primary").remove(); findLastChapter() } else if ($(".j_subscribeBtn").length > 0 || $(".w-all").length > 0) { //网页版 data.currentChapter.vipState = 1; findLastChapter() //updataCurrentChapter(data.currentChapter.id + 1) $(".w-all").remove(); } //findLastChapter() } else if (data.currentChapter.vipState == 1) { if (data.isApp) { chapterNum = $(".read-section").length //findLastChapter() } else { chapterNum = $(".text-wrap").length //findLastChapter() } } }; function getBookChapterInfor() { if (typeof(g_data.book) == "undefined") { //说明是电脑网页端 data.book.bookName = g_data.bookInfo.bookName; data.book.authorName = g_data.bookInfo.authorName; data.currentChapter.chapterName = $(".j_chapterName:last span:first").text(); data.currentChapter.vipState = g_data.chapter.vipStatus; data.currentChapter.contentList = []; data.currentChapter.id = 0; data.isApp = false; } else { //手机网页端 data.book.bookName = g_data.book.bookName; data.book.authorName = g_data.book.authorName; data.currentChapter.chapterName = g_data.chapter.chapterName; data.currentChapter.vipState = g_data.chapter.vipStatus; data.currentChapter.contentList = []; data.currentChapter.id = 0; data.isApp = true; } return data; }; //寻找匹配目录 function findLastChapter() { //遍历目录找到当前目录的url var chapter = ""; if (data.isApp) { data.currentChapter.chapterName = $(".read-section h3").last().text() } else { data.currentChapter.chapterName = $(".text-wrap:last h3 span:first").text() } var current_chapter = data.currentChapter.chapterName; if (data.chapters.length > 0) { console.log("------正在查找阅读到的最新章节------") for (var i = 0, len = data.chapters.length; i < len; i++) { chapter = data.chapters[i].name; if (current_chapter === chapter || current_chapter.indexOf(chapter) != -1 || chapter .indexOf(current_chapter) != -1) { updataCurrentChapter(i); break; } else { updataCurrentChapter(-1); } } } else { updataCurrentChapter(-1); console.log("章节目录没有解析到"); } //return data.currentChapter.id }; function updataCurrentChapter(id) { if (id > -1) { data.currentChapter.id = id; data.currentChapter.chapterName = data.chapters[id].name; data.currentChapter.href = data.chapters[id].href; } else { data.currentChapter.id = id; data.currentChapter.chapterName = "ERROR"; data.currentChapter.href = "www.baidu.com"; } } //根据章节名获取笔趣阁的目录列表,并赋值给data.chapters function getBookContents() { //从当前页面获取小说名称和当前章节 var config = sites[siteId] getBookChapterInfor(); //仅第一次运行 //console.log(data.book.booName); console.log("------开始从 " + config.siteName + " 搜索《 " + data.book.bookName + " 》 ------"); if (config.needName) { config.searchURL = config.searchURL + data.book.bookName } runAsync(config.searchURL, config.method, config.formData + data.book.bookName).then(( result) => { //bookname,authorName ==>搜索===>解析==>href==>请求==>response function getTitleAuthorList(result) { //console.log(result.responseText); var $html = $('
').html(result.responseText); var $table = $($html); var nameList = $(config.bookName, $table), authorList = $(config.authorName, $table), href = ""; if (nameList.length == 0) { console.log("------从 " + config.siteName + " 搜索《 " + data.book.bookName + " 》 失败------"); siteId = siteId + 1; if (siteId < sites.length) { getBookContents() } else { console.log("------未能找到小说,请继续完善地址池------"); } } //console.log("nameList", nameList); //console.log("authorList", authorList); ///console.log($(nameList[0]).text() + "-----" + $(authorList[0]).text()) for (var i = 0, len = nameList.length; i < len; i++) { if (data.book.bookName == $(nameList[i]).text() && (data.book.authorName == $( authorList[ i]).text()) || $(authorList[i]).text().indexOf(data.book.authorName) != - 1) { //console.log($(nameList[i]).text() + "-----" + $(authorList[i]).text()) //console.log(nameList[i]) href = $(nameList[i]).attr("href"); //没有http 说明url要拼接 if (href.indexOf("http") == -1) { href = config.URL + href }; //console.log("href", href) break; } } return runAsync(href); } return getTitleAuthorList(result); }).then((response) => { //response==>解析==>目录列表==>保存到data==>寻找匹配的章节 console.log("------开始从response解析目录-------- "); function getChapterNameHref(response) { var $html = $('
').html(response.responseText); var $table = $($html); var chapters = $(config.chapters, $table); //console.log(chapters); for (var i = 0, len = chapters.length; i < len; i++) { var chapterTmp = { name: "", href: "" }; chapterTmp.name = $(chapters[i]).text(); chapterTmp.href = config.URL + $(chapters[i]).attr("href"); //console.log(chapterTmp); data.chapters.push(chapterTmp); } //寻找匹配的章节 //console.log(data.chapters) findLastChapter(); if (data.currentChapter.id != -1) { //console.log(data.chapters[id].name) return runAsync(data.chapters[data.currentChapter.id].href); } else { console.log("目录没有匹配") return runAsync(data.chapters[0].href); } } return getChapterNameHref(response); }).then((response) => { //response==>解析==>章节内容==>保存到data.currentChapter.contentList==>寻找匹配的章节 parseContent(response.responseText) //console.log(data.chapters) //console.log(data.currentChapter.contentList) }) }; function parseContent(text) { var config = sites[siteId] var $html = $('
').html(text); var $content = $(config.content, $html); // console.log($content); // console.log($($content[0]).text()); // console.log($content[0].text()); //根据config.contentSplit进行不同的读取方式 var contents = [] switch (config.contentSplit) { case "\n\n": contents = $content.text().replace($(config.relace, $html).text(), "").split( "\n\n"); break; case "node": for (var i = 0, len = $content.length; i < len; i++) { contents.push($($content[i]).text()); } break; default: 默认代码块 } data.currentChapter.contentList = contents return contents } // 插入文章 function insertChapter(contents) { var section, paragraph, p = "", i = 0, mlen = -1; if (data.isApp) { //console.log("------开始加载下一章1------"); //手机中插入 chapterNum = $(".read-section").length section = $(".read-article .read-section").last(); //$(".btn-primary", section).remove(); $(".read-article").append(section.clone()); section = $(".read-article .read-section").last(); paragraph = $("p", section).first(); $(".btn-primary", section).remove(); $("p", section).remove(); $("h3", section).text(data.currentChapter.chapterName); for (i = 0, mlen = contents.length; i < mlen; i++) { p = contents[i]; paragraph.text(p); section.append(paragraph.clone()); } //$(".read-article .read-section").eq(-2).remove(); } else { chapterNum = $(".text-wrap").length //web中插入 section = $("#j_chapterBox .text-wrap:last"); $("#j_chapterBox").append(section.clone()); section = $("#j_chapterBox .text-wrap:last"); paragraph = $(".read-content p:first", section); $(".vip-limit-wrap", section).remove(); $(".admire-wrap", section).remove(); $(".read-content p", section).remove(); $("h3:first span:first", section).text(data.currentChapter.chapterName); for (i = 0, mlen = contents.length; i < mlen; i++) { p = contents[i]; paragraph.text(p); $(".read-content", section).append(paragraph.clone()); } //$("#j_chapterBox .text-wrap").eq(-2).remove() } console.log("------已经插入<<" + data.chapters[data.currentChapter.id].name + ">>------") lock = true; }; function runAsync(url, send_type = "GET", data_ry = "") { console.log("请求数据: url: " + url + " method: " + send_type + " data: " + data_ry); var p = new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: send_type, url: url, headers: { "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36 Edg/89.0.774.57" }, data: data_ry, onload: function(response) { //console.log("请求成功"); //console.log(response.responseText); //resolve(response.responseXML); // response.setContentType("text/javascript;charset=UTF-8"); // response.setHeader("Cache-Control", "no-cache"); resolve(response); }, onerror: function(response) { console.log("请求失败: url: " + url + " method: " + send_type + " data: " + data_ry); reject("请求失败: url = " + url); } }); }) return p; }; })();