搬山人
https://www.banshanren.com
s1nnzzz (13776)10/07 04:31
2026-10-07 五段预览检查版。提取前检查整张网页的data-code、验证码按钮和正文段数。发现访问限制或恰好5段时打开本章原网页,需手动完成网站验证后点右上角完成;直接使用浏览器返回的页面,不额外重请求。若仍受限或仍为5段则报错,不保存残缺章节(确实只有5段的真实短章也会触发此检查)。删除未经证实的下一章续页规则。请求UA与内置浏览器一致。导入覆盖后必须清除原书章节缓存再刷新。搜索、目录、分类沿用。封面未解密。已用Rhino/Jsoup验证提取及拦截逻辑;手机验证码流程需实测。
{
"bookSourceName": "搬山人",
"bookSourceUrl": "https:\/\/www.banshanren.com",
"bookSourceGroup": "小说",
"bookSourceType": 0,
"bookUrlPattern": "https?:\/\/www\\.banshanren\\.com\/novel\/[^\/?#]+\/?$",
"enabled": true,
"enabledExplore": true,
"enabledCookieJar": true,
"concurrentRate": "1\/5000",
"lastUpdateTime": "1791318668140",
"bookSourceComment": "2026-10-07 五段预览检查版。提取前检查整张网页的data-code、验证码按钮和正文段数。发现访问限制或恰好5段时打开本章原网页,需手动完成网站验证后点右上角完成;直接使用浏览器返回的页面,不额外重请求。若仍受限或仍为5段则报错,不保存残缺章节(确实只有5段的真实短章也会触发此检查)。删除未经证实的下一章续页规则。请求UA与内置浏览器一致。导入覆盖后必须清除原书章节缓存再刷新。搜索、目录、分类沿用。封面未解密。已用Rhino\/Jsoup验证提取及拦截逻辑;手机验证码流程需实测。",
"header": "@js:JSON.stringify({\"User-Agent\":java.getWebViewUA(),\"Referer\":\"https:\/\/www.banshanren.com\/\"})",
"searchUrl": "\/api\/search?keyword={{java.encodeURI(key)}}&page={{page}}",
"ruleSearch": {
"bookList": "$.model.data[*]",
"name": "$.title",
"author": "$.authors",
"bookUrl": "\/novel\/{{$.slug}}",
"intro": "$.brief",
"kind": "$.tagNames[*]",
"wordCount": "$.wordCount",
"lastChapter": "$.latestUpdate"
},
"exploreUrl": "全部小说::\/all\/0-0-0-0-0-0-1-{{page}}\/\n最近更新::\/all\/0-0-0-0-0-0-2-{{page}}\/\n热门小说::\/all\/0-0-0-0-0-0-3-{{page}}\/\n奇幻玄幻::\/all\/0-4-0-0-0-0-1-{{page}}\/\n现代都市::\/all\/0-3-0-0-0-0-1-{{page}}\/\n穿越重生::\/all\/0-7-0-0-0-0-1-{{page}}\/\n武侠仙侠::\/all\/0-8-0-0-0-0-1-{{page}}\/\nBG言情::\/all\/0-5-0-0-0-0-1-{{page}}\/\nBL耽美::\/all\/0-1-0-0-0-0-1-{{page}}\/\nGL百合::\/all\/0-2-0-0-0-0-1-{{page}}\/",
"ruleExplore": {
"bookList": "@css:.main_box > .novel_list > li.novel_li",
"name": "@css:a.title@text",
"bookUrl": "@css:a.title@href",
"author": "@css:.title_box > .info_box:last-of-type@text##\\s*·[\\s\\S]*$##",
"wordCount": "@css:.title_box > .info_box:last-of-type@text##^[\\s\\S]*·\\s*##",
"kind": "@css:.category_list a@text",
"intro": "@css:.novel_intro_box@text"
},
"ruleBookInfo": {
"name": "@css:.novel_title_box h1@text",
"author": "@css:.novel_title_box [title=作者]@text",
"intro": "@css:meta[property=\"og:description\"]@content",
"kind": "@css:.novel_title_box > .category_list a@text",
"wordCount": "@css:.novel_summary_box.pc > div:last-child b@text",
"tocUrl": "@js:baseUrl",
"lastChapter": "@css:.catalog_top_box .hl@text"
},
"ruleToc": {
"chapterList": "@css:.chapter_list li.volume_chapter",
"chapterName": "@css:a@text",
"chapterUrl": "@css:a@href"
},
"ruleContent": {
"title": "@css:.chapter_content_box > h2@text",
"content": "@js:var pageUrl = String(baseUrl);\nfunction inspectPage(markup) {\n java.setContent(String(markup), pageUrl);\n var documents = java.getElements('@css:html');\n if (documents.size() === 0) throw new Error('没有取得网页,请刷新本章');\n var doc = documents.get(0);\n var chapterBox = doc.select('.chapter_box').first();\n var contentBox = doc.select('.chapter_content_box').first();\n var paragraphs = doc.select('.chapter_content_box > p');\n var code = chapterBox === null ? '' : String(chapterBox.attr('data-code'));\n var notice = String(contentBox === null ? doc.text() : contentBox.text()).replace(\/\\s+\/g, '');\n var captcha = \/系统检测到.{0,15}访问异常|输入验证码后可继续访问\/.test(notice)\n || doc.select('#captcha_btn,[onclick*=toggleCode]').size() > 0;\n var restricted = code !== '' && code !== '0';\n return {doc: doc, paragraphs: paragraphs, count: paragraphs.size(), code: code, captcha: captcha, restricted: restricted};\n}\nvar state = inspectPage(result);\njava.log('搬山人正文检查:段落=' + state.count + ',状态=' + state.code + ',验证提示=' + state.captcha);\nif (state.captcha || state.restricted || state.count === 5) {\n if (typeof java.startBrowserAwait !== 'function') {\n throw new Error('本章疑似受限预览(' + state.count + '段)。请在阅读内置浏览器打开本章原网页完成验证;当前版本不支持自动验证窗口。');\n }\n var verified = java.startBrowserAwait(pageUrl, '请验证并确认本章正文已完整显示,再点右上角完成', false);\n if (verified === null) throw new Error('没有取得验证后的网页,请重新打开本章原网页');\n state = inspectPage(String(verified.body()));\n java.log('搬山人验证后检查:段落=' + state.count + ',状态=' + state.code + ',验证提示=' + state.captcha);\n if (state.captcha || state.restricted) {\n throw new Error('原网页仍限制本章访问(状态=' + state.code + ',' + state.count + '段)。请完成验证码或网站要求的登录后再试。');\n }\n if (state.count === 5) {\n throw new Error('验证后的网页仍只有5段,已停止保存,避免再次缓存截断内容。请检查原网页是否完整;恰好5段的真实短章也会触发此检查。');\n }\n}\nif (state.count === 0) throw new Error('网页未提供正文段落,请在原网页检查访问状态');\nvar clean = state.paragraphs.clone();\nclean.select('span[onclick^=togglePostComment],span[class*=count_]').remove();\nString(clean.outerHtml());\n"
},
"loginUrl": "https:\/\/www.banshanren.com\/"
}