diff --git a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByRegex.kt b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByRegex.kt index 8aee0c218..714a91256 100644 --- a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByRegex.kt +++ b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByRegex.kt @@ -70,7 +70,9 @@ object AnalyzeByRegex { val len = str.length while (index < len) { if (str[index] == '$') { - if (str[index + 1] == '{') { + if (index + 1 >= len) { + break + } else if (str[index + 1] == '{') { if (index > start) { ruleParam.add(str.substring(start, index)) ruleType.add(0) @@ -106,10 +108,29 @@ object AnalyzeByRegex { start = index } } else { - ++index + index++ + } + } else if (str[index] == '{') { + if (index + 1 >= len) { + break + } else if (str[index + 1] == '{') { + if (index > start) { + ruleParam.add(str.substring(start, index)) + ruleType.add(0) + start = index + } + while (index + 1 < len) { + if (str[index] == '}' && str[index + 1] == '}') { + ruleParam.add(str.substring(start + 2, index)) + ruleType.add(-11) + start = index + 2 + break + } + index++ + } } } else { - ++index + index++ } } if (index > start) { @@ -118,25 +139,6 @@ object AnalyzeByRegex { } } - // 存取字符串中的put&get参数 - fun checkKeys(ruleStr: String, analyzer: AnalyzeRule): String { - var str = ruleStr - if (str.contains("@put:{")) { - val putMatcher = Pattern.compile("@put:\\{([^,]*):([^\\}]*)\\}").matcher(str) - while (putMatcher.find()) { - str = str.replace(putMatcher.group(0), "") - analyzer.put(putMatcher.group(1), putMatcher.group(2)) - } - } - if (str.contains("@get:{")) { - val getMatcher = Pattern.compile("@get:\\{([^\\}]*)\\}").matcher(str) - while (getMatcher.find()) { - str = str.replace(getMatcher.group(), analyzer[getMatcher.group(1)] ?: "") - } - } - return str - } - // String数字转int数字的高效方法(利用ASCII值判断) private fun string2Int(s: String): Int { var r = 0 diff --git a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt index fead18fe8..5c4fc6c7f 100644 --- a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt +++ b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt @@ -1,16 +1,15 @@ package io.legado.app.model.analyzeRule -import android.annotation.SuppressLint import android.text.TextUtils import androidx.annotation.Keep import io.legado.app.constant.AppConst.SCRIPT_ENGINE -import io.legado.app.constant.Pattern.EXP_PATTERN import io.legado.app.constant.Pattern.JS_PATTERN import io.legado.app.data.entities.BaseBook import io.legado.app.utils.* import java.util.* import java.util.regex.Pattern import javax.script.SimpleBindings +import kotlin.collections.HashMap /** @@ -18,6 +17,7 @@ import javax.script.SimpleBindings * 统一解析接口 */ @Keep +@Suppress("unused") class AnalyzeRule(private var book: BaseBook? = null) { private var content: Any? = null private var baseUrl: String? = null @@ -121,6 +121,8 @@ class AnalyzeRule(private var book: BaseBook? = null) { if (ruleList.isNotEmpty()) { if (ruleList.isNotEmpty()) result = o for (rule in ruleList) { + putRule(rule.putMap) + rule.makeUpRule(result) result?.let { if (rule.rule.isNotEmpty()) { when (rule.mode) { @@ -129,7 +131,9 @@ class AnalyzeRule(private var book: BaseBook? = null) { getAnalyzeByJSonPath(it).getStringList(rule.rule) Mode.XPath -> result = getAnalyzeByXPath(it).getStringList(rule.rule) - else -> result = getAnalyzeByJSoup(it).getStringList(rule.rule) + Mode.Default -> result = getAnalyzeByJSoup(it).getStringList(rule.rule) + else -> { + } } } if (rule.replaceRegex.isNotEmpty() && result is List<*>) { @@ -189,6 +193,8 @@ class AnalyzeRule(private var book: BaseBook? = null) { content?.let { o -> if (ruleList.isNotEmpty()) result = o for (rule in ruleList) { + putRule(rule.putMap) + rule.makeUpRule(result) result?.let { if (rule.rule.isNotBlank()) { when (rule.mode) { @@ -200,6 +206,8 @@ class AnalyzeRule(private var book: BaseBook? = null) { } else { getAnalyzeByJSoup(it).getString(rule.rule) } + else -> { + } } } if (rule.replaceRegex.isNotEmpty()) { @@ -228,8 +236,11 @@ class AnalyzeRule(private var book: BaseBook? = null) { content?.let { o -> if (ruleList.isNotEmpty()) result = o for (rule in ruleList) { + putRule(rule.putMap) result?.let { when (rule.mode) { + Mode.Regex -> result = + AnalyzeByRegex.getElement(result.toString(), rule.rule.splitNotBlank("&&")) Mode.Js -> result = evalJS(rule.rule, it) Mode.Json -> result = getAnalyzeByJSonPath(it).getObject(rule.rule) Mode.XPath -> result = getAnalyzeByXPath(it).getElements(rule.rule) @@ -255,12 +266,12 @@ class AnalyzeRule(private var book: BaseBook? = null) { content?.let { o -> if (ruleList.isNotEmpty()) result = o for (rule in ruleList) { + putRule(rule.putMap) result?.let { when (rule.mode) { - Mode.Js -> { - if (result == null) result = content - result = evalJS(rule.rule, result) - } + Mode.Regex -> result = + AnalyzeByRegex.getElements(result.toString(), rule.rule.splitNotBlank("&&")) + Mode.Js -> result = evalJS(rule.rule, result) Mode.Json -> result = getAnalyzeByJSonPath(it).getList(rule.rule) Mode.XPath -> result = getAnalyzeByXPath(it).getElements(rule.rule) else -> result = getAnalyzeByJSoup(it).getElements(rule.rule) @@ -291,16 +302,16 @@ class AnalyzeRule(private var book: BaseBook? = null) { } /** - * 分离并执行put规则 + * 分离put规则 */ @Throws(Exception::class) - private fun splitPutRule(ruleStr: String): String { + private fun splitPutRule(ruleStr: String, putMap: HashMap): String { var vRuleStr = ruleStr val putMatcher = putPattern.matcher(vRuleStr) while (putMatcher.find()) { vRuleStr = vRuleStr.replace(putMatcher.group(), "") val map = GSON.fromJsonObject>(putMatcher.group(1)) - map?.let { putRule(map) } + map?.let { putMap.putAll(map) } } return vRuleStr } @@ -308,7 +319,7 @@ class AnalyzeRule(private var book: BaseBook? = null) { /** * 替换@get */ - fun replaceGet(ruleStr: String): String { + private fun replaceGet(ruleStr: String): String { var vRuleStr = ruleStr val getMatcher = getPattern.matcher(vRuleStr) while (getMatcher.find()) { @@ -341,33 +352,33 @@ class AnalyzeRule(private var book: BaseBook? = null) { } return vResult } - - /** - * 替换JS - */ - @SuppressLint("DefaultLocale") - @Throws(Exception::class) - private fun replaceJs(ruleStr: String): String { - var vRuleStr = ruleStr - if (vRuleStr.contains("{{") && vRuleStr.contains("}}")) { - var jsEval: Any - val sb = StringBuffer(vRuleStr.length) - val expMatcher = EXP_PATTERN.matcher(vRuleStr) - while (expMatcher.find()) { - jsEval = evalJS(expMatcher.group(1), content) - if (jsEval is String) { - expMatcher.appendReplacement(sb, jsEval) - } else if (jsEval is Double && jsEval % 1.0 == 0.0) { - expMatcher.appendReplacement(sb, String.format("%.0f", jsEval)) - } else { - expMatcher.appendReplacement(sb, jsEval.toString()) - } - } - expMatcher.appendTail(sb) - vRuleStr = sb.toString() - } - return vRuleStr - } +// +// /** +// * 替换JS +// */ +// @SuppressLint("DefaultLocale") +// @Throws(Exception::class) +// private fun replaceJs(ruleStr: String): String { +// var vRuleStr = ruleStr +// if (vRuleStr.contains("{{") && vRuleStr.contains("}}")) { +// var jsEval: Any +// val sb = StringBuffer(vRuleStr.length) +// val expMatcher = EXP_PATTERN.matcher(vRuleStr) +// while (expMatcher.find()) { +// jsEval = evalJS(expMatcher.group(1), content) +// if (jsEval is String) { +// expMatcher.appendReplacement(sb, jsEval) +// } else if (jsEval is Double && jsEval % 1.0 == 0.0) { +// expMatcher.appendReplacement(sb, String.format("%.0f", jsEval)) +// } else { +// expMatcher.appendReplacement(sb, jsEval.toString()) +// } +// } +// expMatcher.appendTail(sb) +// vRuleStr = sb.toString() +// } +// return vRuleStr +// } /** * 分解规则生成规则列表 @@ -386,27 +397,27 @@ class AnalyzeRule(private var book: BaseBook? = null) { } vRuleStr.startsWith("@Json:", true) -> { mode = Mode.Json + isRegex = true vRuleStr = vRuleStr.substring(6) } - else -> mode = if (isJSON) { - Mode.Json - } else { - Mode.Default + vRuleStr.startsWith(":") -> { + mode = Mode.Regex + vRuleStr = vRuleStr.substring(1) } + else -> mode = + when { + isRegex -> Mode.Regex + isJSON -> Mode.Json + else -> Mode.Default + } } - //分离put规则 - vRuleStr = splitPutRule(vRuleStr) - //替换get值 - vRuleStr = replaceGet(vRuleStr) - //替换js - vRuleStr = replaceJs(vRuleStr) - //拆分为列表 + //拆分为规则列表 var start = 0 var tmp: String val jsMatcher = JS_PATTERN.matcher(vRuleStr) while (jsMatcher.find()) { if (jsMatcher.start() > start) { - tmp = vRuleStr.substring(start, jsMatcher.start()).replace("\n".toRegex(), "").trim { it <= ' ' } + tmp = vRuleStr.substring(start, jsMatcher.start()).replace("\n", "").trim { it <= ' ' } if (!TextUtils.isEmpty(tmp)) { ruleList.add(SourceRule(tmp, mode)) } @@ -415,7 +426,7 @@ class AnalyzeRule(private var book: BaseBook? = null) { start = jsMatcher.end() } if (vRuleStr.length > start) { - tmp = vRuleStr.substring(start).replace("\n".toRegex(), "").trim { it <= ' ' } + tmp = vRuleStr.substring(start).replace("\n", "").trim { it <= ' ' } if (!TextUtils.isEmpty(tmp)) { ruleList.add(SourceRule(tmp, mode)) } @@ -432,6 +443,9 @@ class AnalyzeRule(private var book: BaseBook? = null) { internal var replaceRegex = "" internal var replacement = "" internal var replaceFirst = false + internal val putMap = HashMap() + private val ruleParam = ArrayList() + private val ruleType = ArrayList() init { this.mode = mainMode @@ -475,12 +489,41 @@ class AnalyzeRule(private var book: BaseBook? = null) { if (ruleStrS.size > 3) { replaceFirst = true } + //分离put + rule = splitPutRule(rule, putMap) + rule = replaceGet(rule) + // 拆分表达式替换规则 + AnalyzeByRegex.splitRegexRule(rule, ruleParam, ruleType) + } + + fun makeUpRule(result: Any?) { + val infoVal = StringBuilder() + var j = ruleParam.size + while (j-- > 0) { + val regType = ruleType[j] + if (regType > 0) { + @Suppress("UNCHECKED_CAST") + infoVal.insert(0, (result as List)[regType]) + } else if (regType < 0) { + val jsEval: Any = evalJS(ruleParam[j], result) + if (jsEval is String) { + infoVal.insert(0, jsEval) + } else if (jsEval is Double && jsEval % 1.0 == 0.0) { + infoVal.insert(0, String.format("%.0f", jsEval)) + } else { + infoVal.insert(0, jsEval.toString()) + } + } else { + infoVal.insert(0, ruleParam[j]) + } + } + rule = infoVal.toString() } } enum class Mode { - XPath, Json, Default, Js + XPath, Json, Default, Js, Regex } fun put(key: String, value: String): String { diff --git a/app/src/main/java/io/legado/app/model/webbook/BookChapterList.kt b/app/src/main/java/io/legado/app/model/webbook/BookChapterList.kt index 6719aff4c..2bf02391e 100644 --- a/app/src/main/java/io/legado/app/model/webbook/BookChapterList.kt +++ b/app/src/main/java/io/legado/app/model/webbook/BookChapterList.kt @@ -41,6 +41,9 @@ object BookChapterList { reverse = true listRule = listRule.substring(1) } + if (listRule.startsWith("+")) { + listRule = listRule.substring(1) + } var chapterData = analyzeChapterList(body, baseUrl, tocRule, listRule, book, bookSource, printLog = true) chapterData.chapterList?.let { chapterList.addAll(it) diff --git a/app/src/main/java/io/legado/app/model/webbook/BookList.kt b/app/src/main/java/io/legado/app/model/webbook/BookList.kt index 096d6d83c..06a8ea92d 100644 --- a/app/src/main/java/io/legado/app/model/webbook/BookList.kt +++ b/app/src/main/java/io/legado/app/model/webbook/BookList.kt @@ -48,6 +48,9 @@ object BookList { reverse = true ruleList = ruleList.substring(1) } + if (ruleList.startsWith("+")) { + ruleList = ruleList.substring(1) + } SourceDebug.printLog(bookSource.bookSourceUrl, 1, "解析书籍列表") collections = analyzeRule.getElements(ruleList) if (collections.isEmpty() && bookSource.bookUrlPattern.isNullOrEmpty()) {