可乐小说
https://www.kelexs.com
jianghubailei (2226)4小时前
本书源 来源于laizhiyu大佬 20260816 没想到搜索第二天就废了,signJs新增了大量环境检测,补环境累死我了😭 20260815 修复搜索,全程依靠kimi2.6多轮修复,这次应该能多撑一段时间吧。
{
"bookSourceComment": "本书源 来源于laizhiyu大佬\n\n20260816 没想到搜索第二天就废了,signJs新增了大量环境检测,补环境累死我了😭\n\n20260815 修复搜索,全程依靠kimi2.6多轮修复,这次应该能多撑一段时间吧。",
"bookSourceGroup": "小说",
"bookSourceName": "可乐小说",
"bookSourceType": 0,
"bookSourceUrl": "https:\/\/www.kelexs.com",
"bookUrlPattern": "https?:\/\/www\\.kelexs\\.com\/book\/\\w+\\.html",
"customButton": false,
"customOrder": 7,
"enabled": true,
"enabledCookieJar": true,
"enabledExplore": true,
"eventListener": false,
"exploreUrl": "@js:\nconst groups = {\n \"二次元\": [\n {title:\"原生幻想\", url:\"\/list-25-{{page}}\/\"},\n {title:\"恋爱日常\", url:\"\/list-26-{{page}}\/\"},\n {title:\"衍生同人\", url:\"\/list-27-{{page}}\/\"},\n {title:\"搞笑吐槽\", url:\"\/list-28-{{page}}\/\"}\n ],\n \"男生\": [\n {title:\"玄幻小说\", url:\"\/list-4-{{page}}\/\"},\n {title:\"奇幻小说\", url:\"\/list-5-{{page}}\/\"},\n {title:\"武侠小说\", url:\"\/list-6-{{page}}\/\"},\n {title:\"仙侠小说\", url:\"\/list-7-{{page}}\/\"},\n {title:\"都市小说\", url:\"\/list-8-{{page}}\/\"},\n {title:\"军事小说\", url:\"\/list-9-{{page}}\/\"},\n {title:\"历史小说\", url:\"\/list-10-{{page}}\/\"},\n {title:\"游戏小说\", url:\"\/list-11-{{page}}\/\"},\n {title:\"体育小说\", url:\"\/list-12-{{page}}\/\"},\n {title:\"科幻小说\", url:\"\/list-13-{{page}}\/\"},\n {title:\"诸天无限\", url:\"\/list-14-{{page}}\/\"},\n {title:\"悬疑小说\", url:\"\/list-15-{{page}}\/\"}\n ],\n \"女生\": [\n {title:\"古代言情\", url:\"\/list-16-{{page}}\/\"},\n {title:\"仙侠奇缘\", url:\"\/list-17-{{page}}\/\"},\n {title:\"现代言情\", url:\"\/list-18-{{page}}\/\"},\n {title:\"浪漫青春\", url:\"\/list-19-{{page}}\/\"},\n {title:\"玄幻言情\", url:\"\/list-20-{{page}}\/\"},\n {title:\"悬疑推理\", url:\"\/list-21-{{page}}\/\"},\n {title:\"科幻空间\", url:\"\/list-22-{{page}}\/\"},\n {title:\"游戏竞技\", url:\"\/list-23-{{page}}\/\"},\n {title:\"短篇言情\", url:\"\/list-24-{{page}}\/\"},\n {title:\"轻小说\", url:\"\/list-42-{{page}}\/\"}\n ]\n};\n\nconst list = [];\n\nlist.push({\n title: \"频道\",\n type: \"select\",\n chars: [\"男生\", \"女生\", \"二次元\"],\n default: \"男生\",\n action: \"java.refreshExplore()\",\n style: {layout_flexBasisPercent: 1}\n});\n\nconst selected = infoMap[\"频道\"] || \"男生\";\nconst items = groups[selected];\n\nitems.forEach(item => {\n list.push({\n title: item.title,\n url: item.url,\n style: {layout_flexBasisPercent: 0.29}\n });\n});\n\ninfoMap.save();\nJSON.stringify(list);",
"header": "{\n \"User-Agent\": \"Mozilla\/5.0 (Linux; Android 12; Pixel 6) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/120.0.0.0 Mobile Safari\/537.36\",\n \"Referer\": \"https:\/\/www.kelexs.com\/\"\n}",
"lastUpdateTime": "1786858029069",
"loginUrl": "https:\/\/www.rrssk.com\/0005.html",
"respondTime": 180000,
"ruleBookInfo": {
"author": "[property$=author]@content",
"coverUrl": "[property=og:image]@content",
"intro": "[property=og:description]@content",
"kind": "[property$=category]@content&&\n[property$=status]@content&&\n[property$=update_time]@content",
"lastChapter": "[property$=latest_chapter_name]@content",
"name": "[property$=book_name]@content",
"tocUrl": "@js:\nbaseUrl.replace(\"\/book\/\", \"\/chapter\/\")"
},
"ruleContent": {
"content": "<js>\nlet html = String(result);\nlet chars = \"内暴强情缝肏插逼操潮喷阴艳裸乳荡穴鸡淫苞奸胸射嫩肉骚性蒂茎陰騷奶屄成人药春迷尿粉肛龟头A精屌口狂蜜处女唇道阳虐虫妇液色颜熟交爽臀爆舔做爱欲吹自慰点gG玉幼援抽Bb水母狗户部要了奴小脚痒酥死我兽揉搓捏扣抠棍棒洞密美少摩腿春乱伦露漏浪开巨根菊巴黑豪好肥送艳被干拔乱理白刺体下面诱感快货比日妈你娘婊子配仙火叫在里子宫给聊照流群屁眼马无码友拳洞片黄偷禁套弄位脱光舒服溜舞丢还糜妻换妓招嫖娼aA毛Hh一夜本热推图书娃男抓浑圆饱满润湿滑丰腴韵尤物横陈存娇喘息麻桃透风腹长粗肿胀人紧夹吸撅起来雪发翘硕大胴双草坐挲跨柔软臂瘫媚秘破\";\nvar replacementChars = chars.split(\"\");\nreplacementChars[43] = \"AV\";\nhtml = html.replace(\/<i class=\"icon icon-uni([0-9a-fA-F]{4})\"><\\\/i>\/g, (_, p1) =>\n String.fromCharCode(parseInt(p1, 16)));\nconst decoded = [];\nfor (let i = 0; i < html.length; i++) {\n let code = html.charCodeAt(i);\n if (code >= 0xE001 && code <= 0xE101) {\n decoded.push(replacementChars[code - 0xE001]);\n } else {\n decoded.push(html.charAt(i));\n }\n}\nhtml = decoded.join('');\nconst doc = org.jsoup.Jsoup.parse(html);\nconst contentDiv = doc.selectFirst('.content');\nlet lines = [];\nif (contentDiv) {\n let ps = contentDiv.select('p');\n for (let i = 0; i < ps.size(); i++) {\n let t = String(ps.get(i).text()).replace(\/\\u00a0\/g, ' ').trim();\n if (t) lines.push(t);\n }\n let startIdx = -1;\n for (let i = 0; i < lines.length; i++) {\n if (\/^第\\d+章|^序章|^楔子|^引子\/.test(lines[i])) {\n startIdx = i;\n break;\n }\n }\n if (startIdx > 0) {\n lines = lines.slice(startIdx);\n } else if (startIdx === -1) {\n lines = lines.filter(l => \n !\/本书由.*?发行|版权所有|侵权必究|^\\s*·\\s*$\/.test(l));\n }\n}\nlines.join('\\n');\n<\/js>",
"nextContentUrl": ".btnW a:contains(下一页)@href",
"title": "h1@text"
},
"ruleExplore": {
"author": "a[href*=author]@text",
"bookList": ".dList li",
"bookUrl": ".name a@href",
"coverUrl": "img@src",
"intro": ".intro@text",
"kind": ".dlS.1@dd@text",
"lastChapter": "dt:contains(更新:):eq(1) + dd@text",
"name": ".name a@text"
},
"ruleSearch": {
"author": ".book-card__meta-item:contains(作者:)@ownText",
"bookList": ".book-card",
"bookUrl": ".book-card@onclick\n@js:\nconst window = {\n open(url){\n let t = url.match(\/t=([\\w%]+)\/)?.[1];\n if(!t) return \"\";\n return java.base64Decode(decodeURIComponent(t))\n }\n};\n\neval(result)",
"coverUrl": "img@src",
"intro": ".book-card__desc@text",
"kind": ".book-tag@text&&.book-card__update@text##更新:",
"name": ".book-card__title@text"
},
"ruleToc": {
"chapterList": "@js:\nconst chapters = [];\nif(\/\\\/chapter\\\/\/.test(baseUrl)) {\n let doc = org.jsoup.Jsoup.parse(result);\n let elements = doc.select(\".chapListBody a\");\n elements.forEach(a => {\n let text = a.text().trim();\n let href = a.attr(\"href\");\n chapters.push({text, href})\n })\n} else {\n try {\n let json = JSON.parse(result);\n if (json.data && json.data.length > 0){\n json.data.forEach(ch => {\n chapters.push({\n text: ch.chaptername,\n href: ch.chapterurl\n })\n })\n }\n } catch (e) {\n java.longToast(e.message)\n }\n}\n\nchapters",
"chapterName": "text",
"chapterUrl": "href",
"nextTocUrl": "@js:\n(() => {\nconst nextpageList = java.getStringList(\"@@.dropDown li:not(.cur)@data-p\");\nconst jsUrl = result.match(\/src=\"(\\\/templates\\\/js\\\/[A-Za-z0-9]+\\.js)\"\/)?.[1];\nif(nextpageList.size() == 0 || !jsUrl) return [];\n\nconst host = java.toURL(baseUrl).origin;\nconst cryptHtml = java.ajax(host+jsUrl);\nconst key = cryptHtml.match(\/new AESCrypt\\('([A-Za-z0-9]{32})'\\)\/)?.[1];\nconst iv = cryptHtml.match(\/CryptoJS\\.enc\\.Utf8\\.parse\\('(\\d{16})'\\)\/)?.[1];\nif(!key || !iv) return [];\n\nconst id = baseUrl.match(\/chapter\\\/(.*?)\\.html\/)?.[1];\n\nreturn Array.from(nextpageList, (page) => {\n let postBody = java.createSymmetricCrypto('AES\/CBC\/PKCS5Padding', key, iv).encryptBase64(JSON.stringify({\n id: id,\n page: page\n }));\n return host + '\/index.php?action=loadChapterPage,' + JSON.stringify({\n\t \"method\": \"POST\",\n\t \"body\": \"data=\"+encodeURIComponent(postBody)\n })\n});\n})()"
},
"searchUrl": "@js:\nvar window = this;\n\nvar location = {\n href: \"https:\/\/www.rrssk.com\/0005.html\",\n protocol: \"https:\", host: \"www.rrssk.com\",\n hostname: \"www.rrssk.com\", pathname: \"\/0005.html\",\n search: \"\", hash: \"\"\n};\n\nvar document = {\n documentElement: {\n nodeType: 1, nodeName: \"HTML\", tagName: \"HTML\",\n attributes: {}, style: {},\n ownerDocument: null,\n contains: function() { return false; }\n },\n querySelector: function() { return null; },\n querySelectorAll: function() { return []; },\n addEventListener: function() {},\n createElement: function(tag) {\n return {\n nodeType: 1, nodeName: tag.toUpperCase(),\n ownerDocument: document\n };\n },\n createElementNS: function(ns, tag) {\n return this.createElement(tag);\n },\n getElementsByTagName: function(tag) {\n if (tag === \"html\") return [document.documentElement];\n if (tag === \"head\") return [{}];\n return [];\n },\n location: location\n};\n\ndocument.documentElement.ownerDocument = document;\nwindow.addEventListener = function() {};\nwindow.location = location;\n\nvar navigator = {\n userAgent: String(java.getWebViewUA())\n};\n\nfunction __enc(x) {\n return encodeURIComponent(x).replace(\/[!'()*]\/g, function(c) {\n return '%' + c.charCodeAt(0).toString(16).toUpperCase();\n });\n}\n\n(function() {\n var host = \"https:\/\/www.rrssk.com\";\n \n var homeHtml = String(java.ajax(host + \"\/0005.html\"));\n \n var signJsMatch = homeHtml.match(\/\\\/\\?action=signJs&v=[^\"']+\/);\n if (!signJsMatch) {\n \/\/ java.log(\"[-] 未找到 signJs URL\");\n return;\n }\n var signJsUrl = host + signJsMatch[0];\n \/\/ java.log(\"[+] signJsUrl = \" + signJsUrl);\n \n var verMatch = signJsUrl.match(\/v=(\\d+-\\d+)\/);\n var version = verMatch ? verMatch[1] : \"default\";\n \/\/ java.log(\"[+] version = \" + version);\n \n var tMatch = homeHtml.match(\/name=\"_t\" value=\"([^\"]+)\"\/);\n var t = tMatch ? tMatch[1] : null;\n if (!t) {\n \/\/ java.log(\"[-] 未找到 _t\");\n return;\n }\n \/\/ java.log(\"[+] _t = \" + t);\n \n \/\/ 取 signJs(优先缓存,版本过期自动删)\n var cacheKey = \"rrssk_signJs\";\n var signJsCode = null;\n var cachedRaw = cache.get(cacheKey);\n \n if (cachedRaw) {\n try {\n var cached = JSON.parse(cachedRaw);\n if (cached.version == version) {\n signJsCode = cached.code;\n \/\/ java.log(\"[+] 缓存命中: \" + version);\n } else {\n \/\/ java.log(\"[+] 版本过期: \" + cached.version + \" -> \" + version);\n cache.delete(cacheKey);\n }\n } catch (e) {\n cache.delete(cacheKey);\n }\n }\n \n if (!signJsCode) {\n signJsCode = String(java.ajax(signJsUrl));\n cache.put(cacheKey, JSON.stringify({\n version: version,\n code: signJsCode\n }), 86400);\n \/\/ java.log(\"[+] 网络拉取: \" + version);\n }\n \n eval(signJsCode);\n \/\/ java.log(\"[+] __SIGN_DECOY = \" + window.__SIGN_DECOY);\n \n \/\/ 校验环境检测是否通过\n var testS = window.__SIGN.f(__enc(\"test\"), t, 12345);\n if (testS === \"00000000\") {\n \/\/ java.log(\"[-] 环境检测失败,sign 返回默认值\");\n cache.delete(cacheKey);\n return;\n }\n \n var ts = Math.floor(Date.now() \/ 1000);\n var kw = __enc(key);\n var s = window.__SIGN.f(kw, t, ts);\n \n \/\/ java.log(\"[+] keyword=\" + key + \" _ts=\" + ts + \" _s=\" + s);\n \n var postBody = \"_t=\" + __enc(t)\n + \"&_ts=\" + ts\n + \"&_s=\" + __enc(s)\n + \"&keyword=\" + kw;\n \n var actionMatch = homeHtml.match(\/action=[\"'](\\\/\\?action=\\w+)[\"']\/);\n var action = actionMatch ? actionMatch[1] : \"\";\n if (!action) return;\n \n return host + action + \",\" + JSON.stringify({\n method: \"POST\",\n body: postBody\n });\n})();",
"weight": 0
}