[{"bookSourceComment":"【搜索方式】\n• 关键词搜索：直接在搜索框输入书名或关键词 \n• 标签搜索：在搜索框输入\"tag:标签名\"或\"标签:标签名\"（例：\"tag:玄幻\"）\n  注：标签搜索只能搜索到打上了相应标签小说，冒号不区分中英文\n  有效的搜索：\"tag:无限流\"、\"标签：爽文\"\n  无效的搜索：\"tag:猫\"（没有一个标签包含字样\"猫\"）\n【v2.0 更新说明】\n1. 新增标签搜索功能；\n2. 发现页拓展，具体新增内容自行查看；\n3. 发现页新增\"我的书架\"入口，该书架与网页端菠萝猫书架直接同步；\n【v2.1 更新说明】\n1. 关键词搜索改用 rrssk 站点入口（网站合作更新）；\n2. 通过Java方法提交搜索，需登录（若不登录，搜索有概率跳转到可乐小说）；\n3. 无搜索次数限制；\n【v2.2 更新说明】\n1. 提交搜索改为适应当前网页算法，需登录；\n【注】\n反馈Bug以及书源获取添加QQ群：1040259688，如果网站有算法或加密更新，后续书源可能不再公开发布\n与rrssk相关的书源如可乐小说等，亦可通过相似方法获取，不过不建议混用书源，书库内容是一样的","bookSourceGroup":"菠萝猫","bookSourceName":"菠萝猫小说v2.2","bookSourceType":0,"bookSourceUrl":"https:\/\/www.boluomao.com","bookUrlPattern":"https?:\/\/www\\.boluomao\\.com\/book\/\\d+\\.html","customOrder":1,"enabled":true,"enabledCookieJar":true,"enabledExplore":true,"exploreUrl":"@js:\nvar result = [];\nvar bigStyle = { \"layout_flexGrow\": 1, \"layout_flexBasisPercent\": 1 };\nvar uniformStyle = { \"layout_flexGrow\": 1, \"layout_flexBasisPercent\": 0.25 };\n\n\/* ===== 我的书架（对接书架API，自动遍历分页） ===== *\/\nresult.push({ \"title\": \"我的书架\", \"url\": \"\/api\/bookcase.php?page=1\", \"style\": bigStyle });\n\n\/* ===== 男生（大按钮）+ 子分类平铺 ===== *\/\nresult.push({ \"title\": \"男生\", \"url\": \"\/gender\/boy\/page\/{{page}}\/,{\\\"webView\\\":true}\", \"style\": bigStyle });\nvar boySubs = [\n  [\"全部\",\"\/gender\/boy\/page\/{{page}}\/\"],[\"玄幻\",\"\/gender\/boy\/category\/1\/page\/{{page}}\/\"],\n  [\"奇幻\",\"\/gender\/boy\/category\/2\/page\/{{page}}\/\"],[\"武侠\",\"\/gender\/boy\/category\/3\/page\/{{page}}\/\"],\n  [\"仙侠\",\"\/gender\/boy\/category\/4\/page\/{{page}}\/\"],[\"都市\",\"\/gender\/boy\/category\/5\/page\/{{page}}\/\"],\n  [\"军事\",\"\/gender\/boy\/category\/6\/page\/{{page}}\/\"],[\"历史\",\"\/gender\/boy\/category\/7\/page\/{{page}}\/\"],\n  [\"游戏\",\"\/gender\/boy\/category\/8\/page\/{{page}}\/\"],[\"体育\",\"\/gender\/boy\/category\/9\/page\/{{page}}\/\"],\n  [\"科幻\",\"\/gender\/boy\/category\/10\/page\/{{page}}\/\"],[\"诸天无限\",\"\/gender\/boy\/category\/11\/page\/{{page}}\/\"],\n  [\"悬疑\",\"\/gender\/boy\/category\/12\/page\/{{page}}\/\"]\n];\nfor (var i = 0; i < boySubs.length; i++) {\n  result.push({ \"title\": boySubs[i][0], \"url\": boySubs[i][1] + ',{\\\"webView\\\":true}', \"style\": uniformStyle });\n}\n\n\/* ===== 女生（大按钮）+ 子分类平铺 ===== *\/\nresult.push({ \"title\": \"女生\", \"url\": \"\/gender\/girl\/page\/{{page}}\/,{\\\"webView\\\":true}\", \"style\": bigStyle });\nvar girlSubs = [\n  [\"全部\",\"\/gender\/girl\/page\/{{page}}\/\"],[\"古代言情\",\"\/gender\/girl\/category\/13\/page\/{{page}}\/\"],\n  [\"仙侠奇缘\",\"\/gender\/girl\/category\/14\/page\/{{page}}\/\"],[\"现代言情\",\"\/gender\/girl\/category\/15\/page\/{{page}}\/\"],\n  [\"浪漫青春\",\"\/gender\/girl\/category\/16\/page\/{{page}}\/\"],[\"玄幻言情\",\"\/gender\/girl\/category\/17\/page\/{{page}}\/\"],\n  [\"悬疑推理\",\"\/gender\/girl\/category\/18\/page\/{{page}}\/\"],[\"科幻空间\",\"\/gender\/girl\/category\/19\/page\/{{page}}\/\"],\n  [\"游戏竞技\",\"\/gender\/girl\/category\/20\/page\/{{page}}\/\"],[\"短篇言情\",\"\/gender\/girl\/category\/21\/page\/{{page}}\/\"],\n  [\"耽美\",\"\/gender\/girl\/category\/32\/page\/{{page}}\/\"],[\"百合\",\"\/gender\/girl\/category\/33\/page\/{{page}}\/\"],\n  [\"轻小说\",\"\/gender\/girl\/category\/34\/page\/{{page}}\/\"]\n];\nfor (var i = 0; i < girlSubs.length; i++) {\n  result.push({ \"title\": girlSubs[i][0], \"url\": girlSubs[i][1] + ',{\\\"webView\\\":true}', \"style\": uniformStyle });\n}\n\n\/* ===== 二次元（大按钮）+ 子分类平铺 ===== *\/\nresult.push({ \"title\": \"二次元\", \"url\": \"\/gender\/acg\/page\/{{page}}\/,{\\\"webView\\\":true}\", \"style\": bigStyle });\nvar acgSubs = [\n  [\"全部\",\"\/gender\/acg\/page\/{{page}}\/\"],[\"原生幻想\",\"\/gender\/acg\/category\/22\/page\/{{page}}\/\"],\n  [\"恋爱日常\",\"\/gender\/acg\/category\/23\/page\/{{page}}\/\"],[\"衍生同人\",\"\/gender\/acg\/category\/24\/page\/{{page}}\/\"],\n  [\"搞笑吐槽\",\"\/gender\/acg\/category\/25\/page\/{{page}}\/\"]\n];\nfor (var i = 0; i < acgSubs.length; i++) {\n  result.push({ \"title\": acgSubs[i][0], \"url\": acgSubs[i][1] + ',{\\\"webView\\\":true}', \"style\": uniformStyle });\n}\n\n\/* ===== 热门专题（占位大按钮）+ 入口（去掉\"小说\"字样） ===== *\/\nresult.push({ \"title\": \"热门专题\", \"url\": \"\", \"style\": bigStyle });\nvar hotTopics = [\n  [\"SF轻小说\",\"\/topic\/1.html?p={{page}}\"],[\"刺猬猫\",\"\/topic\/2.html?p={{page}}\"],\n  [\"少年梦\",\"\/topic\/3.html?p={{page}}\"],[\"飞卢\",\"\/topic\/4.html?p={{page}}\"]\n];\nfor (var i = 0; i < hotTopics.length; i++) {\n  result.push({ \"title\": hotTopics[i][0], \"url\": hotTopics[i][1] + ',{\\\"webView\\\":true}', \"style\": uniformStyle });\n}\n\n\/* ===== 最新专题（占位大按钮）+ 入口（去掉\"小说\"字样） ===== *\/\nresult.push({ \"title\": \"最新专题\", \"url\": \"\", \"style\": bigStyle });\nvar newTopics = [\n  [\"息壤\",\"\/topic\/5.html?p={{page}}\"],[\"次元姬\",\"\/topic\/6.html?p={{page}}\"]\n];\nfor (var i = 0; i < newTopics.length; i++) {\n  result.push({ \"title\": newTopics[i][0], \"url\": newTopics[i][1] + ',{\\\"webView\\\":true}', \"style\": uniformStyle });\n}\n\nJSON.stringify(result);","header":"{\n  \"User-Agent\": \"Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/120.0.0.0 Safari\/537.36\"\n}","lastUpdateTime":"1786595204336","loginUrl":"https:\/\/www.boluomao.com\/user\/login\/","respondTime":180000,"ruleBookInfo":{"author":"@css:.bookTitleLeft a.author@text","coverUrl":"@css:meta[property=og:image]@content","intro":"@css:meta[property=og:description]@content || #bookIntro@text","kind":"@css:.info dl dt:contains(分类) + dd a@text && .info dl dt:contains(状态) + dd@text && .info dd.tags-line a@text","lastChapter":"@css:.info a.latest-link@text","name":"@css:h1.font36@text || meta[property=og:title]@content## 全文免费阅读.*|全文免费阅读.*|_.*","tocUrl":"{{baseUrl}}","wordCount":"@css:.txtb > .about .num@text"},"ruleContent":{"content":"<js>\nvar doc = org.jsoup.Jsoup.parse(result);\ndoc.select(\"[style*='display:none']\").remove();\ndoc.select(\"[style*='display: none']\").remove();\ndoc.select(\"[style*='font-size:0']\").remove();\ndoc.select(\"[style*='font-size: 0']\").remove();\ndoc.select(\"[style*='visibility:hidden']\").remove();\ndoc.select(\"[style*='visibility: hidden']\").remove();\n\nvar paragraphs = doc.select(\"div.content p\").toArray();\nvar textList = [];\nfor (var i = 0; i < paragraphs.length; i++) {\n    var txt = paragraphs[i].text().trim();\n    if (txt) {\n        textList.push(txt);\n    }\n}\ntextList.join('\\n\\n');\n<\/js>","nextContentUrl":"<js>\nvar doc = org.jsoup.Jsoup.parse(result);\nvar a = doc.select(\"div.readPage a:contains(下一页)\").first();\nif (a) {\n    var href = a.attr(\"href\");\n    if (href && href.trim() != \"\") {\n        var url = href.startsWith(\"http\") ? href : \"https:\/\/www.boluomao.com\" + href;\n        url + ',{\"webView\":true}';\n    } else {\n        null;\n    }\n} else {\n    null;\n}\n<\/js>"},"ruleExplore":{"author":"@css:span.author@text##作者：","bookList":"<js>\nvar isBookcase = typeof result === 'string' && result.trim().indexOf('{') === 0;\nif (isBookcase) {\n    var allBooks = [];\n    var page = 1;\n    while (page <= 200) {\n        var apiUrl = 'https:\/\/www.boluomao.com\/api\/bookcase.php?page=' + page;\n        var resp;\n        try {\n            resp = java.ajax(apiUrl);\n        } catch (e) {\n            break;\n        }\n        if (!resp || resp.trim().length === 0) {\n            break;\n        }\n        var json;\n        try {\n            json = JSON.parse(resp);\n        } catch (e) {\n            break;\n        }\n        if (!json.data || json.data.length === 0) {\n            break;\n        }\n        for (var i = 0; i < json.data.length; i++) {\n            allBooks.push(json.data[i]);\n        }\n        page++;\n    }\n    var html = '<div class=\"picList\"><ul>';\n    for (var i = 0; i < allBooks.length; i++) {\n        var book = allBooks[i];\n        var href = '\/book\/' + book.articleid + '.html';\n        var name = book.articlename || '';\n        var cover = book.cover || '';\n        var author = book.author || '';\n        var size = book.size != null ? String(book.size) : '';\n        var newest = book.newest_chapter_name || '';\n        html += '<li><div class=\"picb\"><img src=\"' + cover + '\"><\/div>';\n        html += '<div class=\"txtb\"><div class=\"name\"><a href=\"' + href + '\">' + name + '<\/a><\/div>';\n        html += '<span class=\"author\">' + author + '<\/span>';\n        html += '<span class=\"label\">' + newest + '<\/span>';\n        html += '<span class=\"num\">字数：' + size + '<\/span>';\n        html += '<div class=\"intro\"><\/div>';\n        html += '<\/div><\/li>';\n    }\n    html += '<\/ul><\/div>';\n    org.jsoup.Jsoup.parse(html).select('div.picList ul li');\n} else {\n    org.jsoup.Jsoup.parse(result || '').select('div.picList ul li');\n}\n<\/js>","bookUrl":"@css:div.txtb div.name a@href##$##,{\"webView\":true}","coverUrl":"@css:div.picb img@src","intro":"@css:div.intro@text","kind":"@css:span.label@text","name":"@css:div.txtb div.name a@text## 全文免费阅读.*|全文免费阅读.*|_.*","wordCount":"@css:span.num@text##字数："},"ruleSearch":{"author":"<js>\nvar e = org.jsoup.Jsoup.parse(result);\nvar author = '';\nif (e.select('div.book-card__meta').size() > 0) {\n    var spans = e.select('div.book-card__meta span.book-card__meta-item');\n    for (var i = 0; i < spans.size(); i++) {\n        var txt = String(spans.get(i).text());\n        if (txt.indexOf('作者：') === 0) {\n            author = txt.replace('作者：', '').trim();\n            break;\n        }\n    }\n} else {\n    author = String(e.select('span.author').text()).replace('作者：', '');\n}\nauthor;\n<\/js>","bookList":"<js>\nvar doc = org.jsoup.Jsoup.parse(result);\nif (doc.select('div.book-list').size() > 0 || doc.select('div.book-card').size() > 0) {\n    doc.select('div.book-card');\n} else {\n    doc.select('div.picList ul li');\n}\n<\/js>","bookUrl":"<js>\nvar e = org.jsoup.Jsoup.parse(result);\nvar url = '';\nif (e.select('div.book-card').size() > 0) {\n    var onclick = e.select('div.book-card').attr('onclick');\n    var m = onclick.match(\/t=([A-Za-z0-9+\/=]+)\/);\n    if (m) {\n        var decoded = java.base64Decode(m[1]);\n        var idMatch = decoded.match(\/\\\/(\\d+)\\.html\/);\n        if (idMatch) {\n            url = 'https:\/\/www.boluomao.com\/book\/' + idMatch[1] + '.html';\n        } else {\n            url = decoded;\n        }\n    }\n} else {\n    var a = e.select('div.txtb div.name a').first();\n    if (a) {\n        url = a.attr('href');\n        if (url && !url.startsWith('http')) {\n            url = 'https:\/\/www.boluomao.com' + url;\n        }\n    }\n}\nurl ? url + ',{\"webView\":true}' : '';\n<\/js>","coverUrl":"<js>\nvar e = org.jsoup.Jsoup.parse(result);\nif (e.select('div.book-card__cover img').size() > 0) {\n    e.select('div.book-card__cover img').attr('src');\n} else {\n    e.select('div.picb img').attr('src');\n}\n<\/js>","intro":"<js>\nvar e = org.jsoup.Jsoup.parse(result);\nif (e.select('p.book-card__desc').size() > 0) {\n    e.select('p.book-card__desc').text().trim();\n} else {\n    e.select('div.intro').text();\n}\n<\/js>","kind":"<js>\nvar e = org.jsoup.Jsoup.parse(result);\nvar kinds = [];\nfunction addKind(val) {\n    val = String(val).trim();\n    if (val && kinds.indexOf(val) === -1) kinds.push(val);\n}\nif (e.select('div.book-card').size() > 0) {\n    var metaItems = e.select('div.book-card__meta span.book-card__meta-item');\n    for (var i = 0; i < metaItems.size(); i++) {\n        var txt = String(metaItems.get(i).text());\n        if (txt.indexOf('分类：') === 0) {\n            addKind(txt.replace('分类：', ''));\n        }\n    }\n    addKind(e.select('span.book-tag--status').text());\n    var tags = e.select('div.book-card__tags span.book-tag:not(.book-tag--status)');\n    for (var i = 0; i < tags.size(); i++) {\n        addKind(tags.get(i).text());\n    }\n    var update = String(e.select('span.book-card__update').text()).replace('更新：', '');\n    addKind(update);\n} else {\n    addKind(e.select('span.label').text());\n}\nkinds.join(',');\n<\/js>","name":"<js>\nvar e = org.jsoup.Jsoup.parse(result);\nif (e.select('h3.book-card__title').size() > 0) {\n    e.select('h3.book-card__title').text();\n} else {\n    var t = e.select('div.txtb div.name a').text();\n    String(t).replace(\/ 全文免费阅读.*|全文免费阅读.*|_.*\/, '');\n}\n<\/js>","wordCount":"<js>\nvar e = org.jsoup.Jsoup.parse(result);\nif (e.select('span.num').size() > 0) {\n    String(e.select('span.num').text()).replace('字数：', '');\n} else {\n    '';\n}\n<\/js>"},"ruleToc":{"chapterList":"@css:#chapters .direList ul li a","chapterName":"text","chapterUrl":"href##$##,{\"webView\":true}","nextTocUrl":"<js>\nvar doc = org.jsoup.Jsoup.parse(result);\nvar nextA = doc.select(\"div.page-range-list span.cur + a\").first();\nif (nextA) {\n    var href = nextA.attr(\"href\");\n    if (href && href.trim() != \"\") {\n        var url = href.startsWith(\"http\") ? href : \"https:\/\/www.boluomao.com\" + href;\n        url + ',{\"webView\":true}';\n    } else {\n        null;\n    }\n} else {\n    null;\n}\n<\/js>"},"searchUrl":"<js>\n(function() {\n    \/\/ 1. 判断是否是标签搜索\n    function isTagSearch(key) {\n        return \/^(tag|标签)[:：]\/.test(key);\n    }\n  \n    if (isTagSearch(key)) {\n        java.longToast('🔍 正在使用标签搜索（菠萝猫搜索）');\n        var tag = key.replace(\/^(tag|标签)[:：]\/, '').trim();\n        var baseUrl = 'https:\/\/www.boluomao.com\/tag\/' + java.encodeURI(tag) + '\/';\n        return page > 1 ? baseUrl + 'page\/' + page + '\/' : baseUrl;\n    }\n\n    \/\/ 2. 关键词搜索逻辑 (通过缓存和 rrssk.com 动态签名)\n    var cacheKey = \"rrssk_find_url_\" + java.md5Encode(key);\n    var targetUrl = cache.get(cacheKey);\n\n    if (!targetUrl) {\n        java.longToast('🔍 正在安全连接并检索书籍...');\n        var window = {};\n      \n        \/\/ 获取中转页 HTML\n        var resHtml = java.get('https:\/\/www.rrssk.com\/boluomao.html', {\n            \"User-Agent\": \"Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/120.0.0.0 Safari\/537.36\",\n            \"Referer\": \"https:\/\/www.rrssk.com\/\"\n        }).body();\n\n        \/\/ 提取 _t\n        var tMatch = resHtml.match(\/name=\"_t\"\\s+value=\"([^\"]+)\"\/);\n        if (!tMatch) {\n            throw new Error(\"无法从中转页获取到签名令牌(_t)\");\n        }\n        var tVal = tMatch[1];\n\n        \/\/ 依次执行所有内联 script，加载签名函数及可能用到的加密工具函数\n        var scriptRegex = \/<script[^>]*>([\\s\\S]*?)<\\\/script>\/gi;\n        var match;\n        var foundSign = false;\n        while ((match = scriptRegex.exec(resHtml)) !== null) {\n            var code = match[1];\n            if (code && code.trim().length > 0) {\n                try {\n                    eval(code);\n                    if (code.indexOf(\"__SIGN\") !== -1) {\n                        foundSign = true;\n                    }\n                } catch(e) {\n                    \/\/ 忽略部分因缺少浏览器DOM环境引起的无害报错\n                }\n            }\n        }\n\n        if (!foundSign || !window.__SIGN || typeof window.__SIGN.f !== 'function') {\n            throw new Error(\"未能成功初始化动态签名算法，请反馈至作者维护\");\n        }\n\n        \/\/ 与 PHP rawurlencode 完全一致的 RFC3986 编码\n        function __enc(x) {\n            return encodeURIComponent(x).replace(\/[!'()*]\/g, function(c) {\n                return '%' + c.charCodeAt(0).toString(16).toUpperCase();\n            });\n        }\n\n        var ts = Math.floor(Date.now() \/ 1000);\n        var s = window.__SIGN.f(__enc(key), tVal, ts);\n\n        \/\/ 构造载荷提交 POST 搜索请求\n        var postData = \"action=search&_t=\" + tVal + \"&_ts=\" + ts + \"&_s=\" + s + \"&keyword=\" + java.encodeURI(key);\n        var postRes = java.post(\"https:\/\/www.rrssk.com\/?action=search\", postData, {\n            \"Content-Type\": \"application\/x-www-form-urlencoded\",\n            \"Referer\": \"https:\/\/www.rrssk.com\/boluomao.html\",\n            \"User-Agent\": \"Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/120.0.0.0 Safari\/537.36\"\n        });\n\n        \/\/ 获取最终的 find 重定向页面地址\n        targetUrl = postRes.url().toString();\n\n        if (!targetUrl || targetUrl.indexOf(\"action=find\") === -1) {\n            var loc = postRes.header(\"Location\");\n            if (loc) {\n                if (!loc.startsWith(\"http\")) {\n                    targetUrl = \"https:\/\/www.rrssk.com\" + (loc.startsWith(\"\/\") ? \"\" : \"\/\") + loc;\n                } else {\n                    targetUrl = loc;\n                }\n            }\n        }\n\n        if (!targetUrl || targetUrl.indexOf(\"action=find\") === -1) {\n            throw new Error(\"未能进入有效的搜索结果页面，请尝试重新搜索\");\n        }\n\n        \/\/ 规范化 URL，剔除原有 page 参数以供后续动态翻页拼接\n        targetUrl = targetUrl.replace(\/[&?]page=\\d+\/g, \"\");\n        cache.put(cacheKey, targetUrl, 300); \/\/ 结果地址写入缓存 (有效期 5 分钟)\n    }\n\n    var conn = targetUrl.indexOf(\"?\") !== -1 ? \"&\" : \"?\";\n    return targetUrl + conn + \"page=\" + page;\n})()\n<\/js>","weight":0}]