From 5d55e0e5a8f8762219956323503cce98f42b527b Mon Sep 17 00:00:00 2001 From: bushixuanqi <57338301+bushixuanqi@users.noreply.github.com> Date: Sun, 4 Jul 2021 01:53:30 +0800 Subject: [PATCH 01/12] Update AnalyzeByJSoup.kt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 0. 新增专门用于切分各种规则的类,分解完所有规则后才切片,其余操作都只改变变量指向规则字符串中的位置。暂时只用于处理三大规则的“&&”、“||”,“%%”、“@”切分,以后将扩展到全部解析规则。 改进jsonPath,jsoup,xpath中的规则切分方法,允许查询规则的正则或字符串中存在“&&”,“||”,“%%”,“@”而不切错。 /** * 改进解析方法 * 解决阅读”&&“、”||“与jsonPath支持的”&&“、”||“之间的冲突 * 解决{$.rule}形式规则可能匹配错误的问题,旧规则用正则解析内容含‘}’的json文本时,用规则中的字段去匹配这种内容时,会匹配错误.现改用平衡嵌套方法解决这个问题 * */ 1. 加强AnalyzeByJSoup中的索引写法 /** * 1.支持阅读原有写法,':'分隔索引,!或.表示筛选方式,索引可为负数 * * 例如 tag.div.-1:10:2 或 tag.div!0:3 * * 2. 支持与jsonPath类似的[]索引写法 * * 格式形如 [it,it,。。。] 或 [!it,it,。。。] 其中[!开头表示筛选方式为排除,it为单个索引或区间。 * * 区间格式为 start:end 或 start:end:step,其中start为0可省略,end为-1可省略。 * * 索引,区间两端及间隔都支持负数 * * 例如 tag.div[-1, 3:-2:-10, 2] * * 特殊用法 tag.div[-1:0] 可在任意地方让列表反向 * * */ ------------------- 已测试过各种“&&”、“||”,“%%”切分的规则及两者索引写法,没发现大问题,坤飞大大可以再测试看看 --- .../app/model/analyzeRule/AnalyzeByJSoup.kt | 171 ++++++++++-------- 1 file changed, 92 insertions(+), 79 deletions(-) diff --git a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSoup.kt b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSoup.kt index 37e9bfd1c..6f45f9f21 100644 --- a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSoup.kt +++ b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSoup.kt @@ -184,108 +184,113 @@ class AnalyzeByJSoup(doc: Any) { } /** - * '.'开头表示选择元素,或'!'开头排除那些元素。两者都支持以索引列表按顺序指定元素列表 - * ':'分隔不同索引或区间 - * 区间格式为 start~end+step,其中start为0可省略,end为-1可省略。 + * 1.支持阅读原有写法,':'分隔索引,!或.表示筛选方式,索引可为负数 + * + * 例如 tag.div.-1:10:2 或 tag.div!0:3 + * + * 2. 支持与jsonPath类似的[]索引写法 + * + * 格式形如 [it,it,。。。] 或 [!it,it,。。。] 其中[!开头表示筛选方式为排除,it为单个索引或区间。 + * + * 区间格式为 start:end 或 start:end:step,其中start为0可省略,end为-1可省略。 + * * 索引,区间两端及间隔都支持负数 - * 例如 tag.div.-1:3~-2+-10:2 - * 特殊用法 tag.div.-1~0 可在任意地方让列表反向 + * + * 例如 tag.div[-1, 3:-2:-10, 2] + * + * 特殊用法 tag.div[-1:0] 可在任意地方让列表反向 + * * */ + fun findIndexSet( rule:String ): IndexSet { val indexSet = IndexSet() - val rus = rule.trim{ it <= ' '} - var last = rus.length - var step = 0 //区间步长,为0表示没设置区间 - var curInt: Int //当前数字 - var end = 0 //暂存区间结束数字 - - var range = false //true表示当前在区间开头,false表示当前在区间结尾 + var len = rus.length + var curInt: Int? //当前数字 var curMinus = false //当前数字是否为负 - var curEndMinus = false //当前区间右端数字是否为负 - var curStepMinus = false //当前区间间隔数字是否为负 - + val curList = mutableListOf() //当前数字区间 var l = "" //暂存数字字符串 - while (last --> 1 ){ //逆向遍历,至少有两位前置字符,如 p. + val head = rus[rus.length-1] == ']' //是否为常规索引写法 - val rl = rus[last] - if(rl == ' ' )continue //跳过空格 - if( rl in '0'..'9') l+= rl //将数值累接入临时字串中,遇到分界符才取出 - else if(rl == '-') curMinus = true - else if( rl in arrayOf('+','~','!','.',':')) { //分界符号 '+','~','!','.',':' + if(head){ //常规索引写法[index...] - when ( rl ) { + len-- //跳过尾部']' - '+' ->{ - curStepMinus = curMinus - step = l.toInt() //区间间隔数 - } + while (len-- > 0) { //逆向遍历,至少有一位前置字符,如 [ - '~' -> { - range = true - curEndMinus = curMinus + var rl = rus[len] + if (rl == ' ') continue //跳过空格 - if (l.isEmpty()) { - end = -1 //省略区间右端,设置为-1 - continue - } else end = l.toInt() - } + if (rl in '0'..'9') l += rl //将数值累接入临时字串中,遇到分界符才取出 + else if (rl == '-') curMinus = true + else { - else -> { + curInt = if (l.isEmpty()) null else if (curMinus) -l.toInt() else l.toInt() //当前数字 - curInt = if(l.isEmpty()) 0 /* 省略区间左端,设置为0 */ else if(curMinus) - l.toInt() else l.toInt() //区间左端数,省略则为最左边 + when (rl) { - indexSet.indexs.add( //压入以下值,为保证查找顺序,区间和单个索引都添加到同一集合 + ':' -> curList.add(curInt) //区间右端或区间间隔 - if ( range ) { + else -> { - range = false //重置 + indexSet.indexs.add( //压入以下值,为保证查找顺序,区间和单个索引都添加到同一集合 - if (curEndMinus) { - end = -end - curEndMinus = false //重置 - } + if(curList.isEmpty()) curInt!! //区间为空,表明当前是单个索引,单个索引不能空 - //没设置间隔时,间隔为1。将区间的三项数据压入,在获取到元素数量后再计算负数索引,并展开区间 - if( step == 0 ) Triple(curInt, end, 1) + else Triple(curInt, curList.last(), if(curList.size == 2) curList.first() else 1) //否则为区间,列表最后压入的是区间右端,若列表有两位则最先压入了间隔 - else { + ) - if (curStepMinus) { - step = -step - curStepMinus = false //重置 - } + if(rl == '!'){ + indexSet.split='!' + do{ rl = rus[--len] } while (len > 0 && rl == ' ')//跳过所有空格 + } - val stepx = step - step = 0 //重置 + if(rl == '[') return indexSet.apply { + beforeRule = rus.substring(0, len) + } //遇到索引边界,返回结果 - //将区间的三项数据压入,在获取到元素数量后再计算负数索引,并展开区间 - Triple(curInt, end, stepx) + if(rl != ',') break //非索引结构,跳出 - } + } + } - }else curInt //压入单个索引,在获取到元素数量后再计算负数索引 + l = "" //清空 + curMinus = false //重置 + } + } + } else while (len --> 1) { //阅读原本写法,逆向遍历,至少两位前置字符,如 p. - ) + val rl = rus[len] + if (rl == ' ') continue //跳过空格 - if( rl == '!' || rl == '.' ) return indexSet.apply{ - split = rl - beforeRule = rus.substring(0, last) - } + if (rl in '0'..'9') l += rl //将数值累接入临时字串中,遇到分界符才取出 + else if (rl == '-') curMinus = true + else { + + if(rl == '!' || rl == '.' || rl == ':') { //分隔符或起始符 + + indexSet.indexDefault.add(if (curMinus) -l.toInt() else l.toInt()) // 当前数字追加到列表 + + if (rl != ':') return indexSet.apply { //rl == '!' || rl == '.' + split = rl + beforeRule = rus.substring(0, len) } - } + + }else break //非索引结构,跳出循环 + l = "" //清空 curMinus = false //重置 } - else break - } - return indexSet.apply{ beforeRule = rus } //非索引格式 + return indexSet.apply{ + split = ' ' + beforeRule = rus } //非索引格式 } /** @@ -321,7 +326,7 @@ class AnalyzeByJSoup(doc: Any) { for (pcInt in indexSet) elements[pcInt] = null - elements.removeAll(listOf(null)) //测试过,这样就能把全部null元素删除 + elements.removeAll(listOf(null)) //测试过,这样就行 }else if(filterType == '.'){ //选择 @@ -412,38 +417,46 @@ class AnalyzeByJSoup(doc: Any) { return textS } - data class IndexSet(var split:Char = ' ', + data class IndexSet(var split:Char = '.', var beforeRule:String = "", + val indexDefault:MutableList = mutableListOf(), val indexs:MutableList = mutableListOf()){ fun getIndexs(len:Int): MutableSet { val indexSet = mutableSetOf() - val lastIndexs = indexs.size - 1 + val lastIndexs = (indexDefault.size - 1).takeIf { it !=-1 } ?: indexs.size -1 + + + if(indexs.isEmpty())for (ix in lastIndexs downTo 0 ){ //indexs为空,表明是非[]式索引,集合是逆向遍历插入的,所以这里也逆向遍历,好还原顺序 + + val it = indexDefault[ix] + if(it in 0 until len) indexSet.add(it) //将正数不越界的索引添加到集合 + else if(it < 0 && len >= -it) indexSet.add(it + len) //将负数不越界的索引添加到集合 - for (ix in lastIndexs downTo 0 ){ //逆向遍历,还原顺序 + }else for (ix in lastIndexs downTo 0 ){ //indexs不空,表明是[]式索引,集合是逆向遍历插入的,所以这里也逆向遍历,好还原顺序 if(indexs[ix] is Triple<*, *, *>){ //区间 - var (start, end, step) = indexs[ix] as Triple //还原储存时的类型 + val (startx, endx, stepx) = indexs[ix] as Triple //还原储存时的类型 - if (start >= 0) { - if (start >= len) start = len - 1 //右端越界,设置为最大索引 - } else start = if (-start <= len) len + start /* 将负索引转正 */ else 0 //左端越界,设置为最小索引 + val start = if (startx == null) 0 //左端省略表示0 + else if (startx >= 0) if (startx < len) startx else len - 1 //右端越界,设置为最大索引 + else if (-startx <= len) len + startx /* 将负索引转正 */ else 0 //左端越界,设置为最小索引 - if (end >= 0) { - if (end >= len) end = len - 1 //右端越界,设置为最大索引 - } else end = if (-end <= len) len + end /* 将负索引转正 */ else 0 //左端越界,设置为最小索引 + val end = if (endx == null) len - 1 //右端省略表示 len - 1 + else if (endx >= 0) if (endx < len) endx else len - 1 //右端越界,设置为最大索引 + else if (-endx <= len) len + endx /* 将负索引转正 */ else 0 //左端越界,设置为最小索引 - if (start == end || step >= len) { //两端相同,区间里只有一个数。或间隔过大,区间实际上仅有首位 + if (start == end || stepx >= len) { //两端相同,区间里只有一个数。或间隔过大,区间实际上仅有首位 - indexSet.add(start) + indexSet.add(stepx) continue } - step = if (step > 0) step else if (-step < len) step + len else 1 //最小正数间隔为1 + val step = if (stepx > 0) stepx else if (-stepx < len) stepx + len else 1 //最小正数间隔为1 //将区间展开到集合中,允许列表反向。 indexSet.addAll(if (end > start) start..end step step else start downTo end step step) From db6db67f1e6209b06fc07fc80c28b2dc48256732 Mon Sep 17 00:00:00 2001 From: bushixuanqi <57338301+bushixuanqi@users.noreply.github.com> Date: Sun, 4 Jul 2021 01:54:56 +0800 Subject: [PATCH 02/12] Update AnalyzeByJSonPath.kt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 注释优化 --- .../model/analyzeRule/AnalyzeByJSonPath.kt | 225 +++--------------- 1 file changed, 33 insertions(+), 192 deletions(-) diff --git a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSonPath.kt b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSonPath.kt index e9abb23b2..b45b89643 100644 --- a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSonPath.kt +++ b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSonPath.kt @@ -1,192 +1,33 @@ -package io.legado.app.model.analyzeRule - -import androidx.annotation.Keep -import com.jayway.jsonpath.JsonPath -import com.jayway.jsonpath.ReadContext -import java.util.* - -@Suppress("RegExpRedundantEscape") -@Keep -class AnalyzeByJSonPath(json: Any) { - - companion object { - - fun parse(json: Any): ReadContext { - return when (json) { - is ReadContext -> json - is String -> JsonPath.parse(json) //JsonPath.parse(json) - else -> JsonPath.parse(json) //JsonPath.parse(json) - } - } - } - - private var ctx: ReadContext = parse(json) - - /** - * 改进解析方法 - * 解决阅读”&&“、”||“与jsonPath支持的”&&“、”||“之间的冲突 - * 解决{$.rule}形式规则可能匹配错误的问题,旧规则正则解析内容含‘}’的json文本,用规则中的字段去匹配这种内容时,会匹配错误.现改用平衡嵌套方法解决这个问题 - * */ - fun getString(rule: String): String? { - if (rule.isEmpty()) return null - var result: String - val ruleAnalyzes = RuleAnalyzer(rule) - val rules = ruleAnalyzes.splitRule("&&","||") - - if (rules.size == 1) { - - ruleAnalyzes.reSetPos() //将pos重置为0,复用解析器 - - result = ruleAnalyzes.innerRule("{$."){ getString(it) } //替换所有{$.rule...} - - if (result.isEmpty()) { //st为空,表明无成功替换的内嵌规则 - - try { - - val ob = ctx.read(rule) - - result =(if (ob is List<*>) { - - val builder = StringBuilder() - for (o in ob) { - builder.append(o).append("\n") - } - - builder.deleteCharAt(builder.lastIndex) //删除末尾赘余换行 - - builder - - } else ob).toString() - - } catch (ignored: Exception) { - } - - } - - return result - - } else { - val textList = arrayListOf() - for (rl in rules) { - val temp = getString(rl) - if (!temp.isNullOrEmpty()) { - textList.add(temp) - if (ruleAnalyzes.elementsType == "||") { - break - } - } - } - return textList.joinToString("\n") - } - } - - internal fun getStringList(rule: String): List { - val result = ArrayList() - if (rule.isEmpty()) return result - val ruleAnalyzes = RuleAnalyzer(rule) - val rules = ruleAnalyzes.splitRule("&&","||","%%") - - if (rules.size == 1) { - - ruleAnalyzes.reSetPos() //将pos重置为0,复用解析器 - - val st = ruleAnalyzes.innerRule("{$."){ getString(it) } //替换所有{$.rule...} - - if (st.isEmpty()) { //st为空,表明无成功替换的内嵌规则 - - try { - - val obj = ctx.read(rule) //kotlin的Any型返回值不包含null ,删除赘余 ?: return result - - if (obj is List<*>) { - - for (o in obj) result.add(o.toString()) - - } else result.add(obj.toString()) - - } catch (ignored: Exception) { - } - - }else result.add(st) - - return result - - } else { - val results = ArrayList>() - for (rl in rules) { - val temp = getStringList(rl) - if (temp.isNotEmpty()) { - results.add(temp) - if (temp.isNotEmpty() && ruleAnalyzes.elementsType == "||") { - break - } - } - } - if (results.size > 0) { - if ("%%" == ruleAnalyzes.elementsType) { - for (i in results[0].indices) { - for (temp in results) { - if (i < temp.size) { - result.add(temp[i]) - } - } - } - } else { - for (temp in results) { - result.addAll(temp) - } - } - } - return result - } - } - - internal fun getObject(rule: String): Any { - return ctx.read(rule) - } - - internal fun getList(rule: String): ArrayList? { - val result = ArrayList() - if (rule.isEmpty()) return result - val ruleAnalyzes = RuleAnalyzer(rule) - val rules = ruleAnalyzes.splitRule("&&","||","%%") - if (rules.size == 1) { - ctx.let { - try { - return it.read>(rules[0]) - } catch (e: Exception) { - e.printStackTrace() - } - } - return null - } else { - val results = ArrayList>() - for (rl in rules) { - val temp = getList(rl) - if (temp != null && temp.isNotEmpty()) { - results.add(temp) - if (temp.isNotEmpty() && ruleAnalyzes.elementsType == "||") { - break - } - } - } - if (results.size > 0) { - if ("%%" == ruleAnalyzes.elementsType) { - for (i in 0 until results[0].size) { - for (temp in results) { - if (i < temp.size) { - temp[i]?.let { result.add(it) } - } - } - } - } else { - for (temp in results) { - result.addAll(temp) - } - } - } - } - return result - } - -} +0. 新增专门用于切分各种规则的类,分解完所有规则后才切片,其余操作都只改变变量指向规则字符串中的位置。暂时只用于处理三大规则的“&&”、“||”,“%%”、“@”切分,以后将扩展到全部解析规则。 + + 改进jsonPath,jsoup,xpath中的规则切分方法,允许查询规则的正则或字符串中存在“&&”,“||”,“%%”,“@”而不切错。 + +/** +* 改进解析方法 +* 解决阅读”&&“、”||“与jsonPath支持的”&&“、”||“之间的冲突 +* 解决{$.rule}形式规则可能匹配错误的问题,旧规则用正则解析内容含‘}’的json文本时,用规则中的字段去匹配这种内容时,会匹配错误.现改用平衡嵌套方法解决这个问题 +* */ + +1. 加强AnalyzeByJSoup中的索引写法 + +/** +* 1.支持阅读原有写法,':'分隔索引,!或.表示筛选方式,索引可为负数 +* +* 例如 tag.div.-1:10:2 或 tag.div!0:3 +* +* 2. 支持与jsonPath类似的[]索引写法 +* +* 格式形如 [it,it,。。。] 或 [!it,it,。。。] 其中[!开头表示筛选方式为排除,it为单个索引或区间。 +* +* 区间格式为 start:end 或 start:end:step,其中start为0可省略,end为-1可省略。 +* +* 索引,区间两端及间隔都支持负数 +* +* 例如 tag.div[-1, 3:-2:-10, 2] +* +* 特殊用法 tag.div[-1:0] 可在任意地方让列表反向 +* +* */ + + ------------------- + 已测试过各种“&&”、“||”,“%%”切分的规则及两者索引写法,没发现大问题,坤飞大大可以再测试看看 From 6caa0c39a7913725daf1551ab7d60737f2807a11 Mon Sep 17 00:00:00 2001 From: bushixuanqi <57338301+bushixuanqi@users.noreply.github.com> Date: Sun, 4 Jul 2021 01:57:04 +0800 Subject: [PATCH 03/12] Update AnalyzeByJSonPath.kt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 注释优化,复制错代码修正 --- .../model/analyzeRule/AnalyzeByJSonPath.kt | 225 +++++++++++++++--- 1 file changed, 192 insertions(+), 33 deletions(-) diff --git a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSonPath.kt b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSonPath.kt index b45b89643..63e02ec8c 100644 --- a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSonPath.kt +++ b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSonPath.kt @@ -1,33 +1,192 @@ -0. 新增专门用于切分各种规则的类,分解完所有规则后才切片,其余操作都只改变变量指向规则字符串中的位置。暂时只用于处理三大规则的“&&”、“||”,“%%”、“@”切分,以后将扩展到全部解析规则。 - - 改进jsonPath,jsoup,xpath中的规则切分方法,允许查询规则的正则或字符串中存在“&&”,“||”,“%%”,“@”而不切错。 - -/** -* 改进解析方法 -* 解决阅读”&&“、”||“与jsonPath支持的”&&“、”||“之间的冲突 -* 解决{$.rule}形式规则可能匹配错误的问题,旧规则用正则解析内容含‘}’的json文本时,用规则中的字段去匹配这种内容时,会匹配错误.现改用平衡嵌套方法解决这个问题 -* */ - -1. 加强AnalyzeByJSoup中的索引写法 - -/** -* 1.支持阅读原有写法,':'分隔索引,!或.表示筛选方式,索引可为负数 -* -* 例如 tag.div.-1:10:2 或 tag.div!0:3 -* -* 2. 支持与jsonPath类似的[]索引写法 -* -* 格式形如 [it,it,。。。] 或 [!it,it,。。。] 其中[!开头表示筛选方式为排除,it为单个索引或区间。 -* -* 区间格式为 start:end 或 start:end:step,其中start为0可省略,end为-1可省略。 -* -* 索引,区间两端及间隔都支持负数 -* -* 例如 tag.div[-1, 3:-2:-10, 2] -* -* 特殊用法 tag.div[-1:0] 可在任意地方让列表反向 -* -* */ - - ------------------- - 已测试过各种“&&”、“||”,“%%”切分的规则及两者索引写法,没发现大问题,坤飞大大可以再测试看看 +package io.legado.app.model.analyzeRule + +import androidx.annotation.Keep +import com.jayway.jsonpath.JsonPath +import com.jayway.jsonpath.ReadContext +import java.util.* + +@Suppress("RegExpRedundantEscape") +@Keep +class AnalyzeByJSonPath(json: Any) { + + companion object { + + fun parse(json: Any): ReadContext { + return when (json) { + is ReadContext -> json + is String -> JsonPath.parse(json) //JsonPath.parse(json) + else -> JsonPath.parse(json) //JsonPath.parse(json) + } + } + } + + private var ctx: ReadContext = parse(json) + + /** + * 改进解析方法 + * 解决阅读”&&“、”||“与jsonPath支持的”&&“、”||“之间的冲突 + * 解决{$.rule}形式规则可能匹配错误的问题,旧规则用正则解析内容含‘}’的json文本时,用规则中的字段去匹配这种内容时,会匹配错误.现改用平衡嵌套方法解决这个问题 + * */ + fun getString(rule: String): String? { + if (rule.isEmpty()) return null + var result: String + val ruleAnalyzes = RuleAnalyzer(rule) + val rules = ruleAnalyzes.splitRule("&&","||") + + if (rules.size == 1) { + + ruleAnalyzes.reSetPos() //将pos重置为0,复用解析器 + + result = ruleAnalyzes.innerRule("{$."){ getString(it) } //替换所有{$.rule...} + + if (result.isEmpty()) { //st为空,表明无成功替换的内嵌规则 + + try { + + val ob = ctx.read(rule) + + result =(if (ob is List<*>) { + + val builder = StringBuilder() + for (o in ob) { + builder.append(o).append("\n") + } + + builder.deleteCharAt(builder.lastIndex) //删除末尾赘余换行 + + builder + + } else ob).toString() + + } catch (ignored: Exception) { + } + + } + + return result + + } else { + val textList = arrayListOf() + for (rl in rules) { + val temp = getString(rl) + if (!temp.isNullOrEmpty()) { + textList.add(temp) + if (ruleAnalyzes.elementsType == "||") { + break + } + } + } + return textList.joinToString("\n") + } + } + + internal fun getStringList(rule: String): List { + val result = ArrayList() + if (rule.isEmpty()) return result + val ruleAnalyzes = RuleAnalyzer(rule) + val rules = ruleAnalyzes.splitRule("&&","||","%%") + + if (rules.size == 1) { + + ruleAnalyzes.reSetPos() //将pos重置为0,复用解析器 + + val st = ruleAnalyzes.innerRule("{$."){ getString(it) } //替换所有{$.rule...} + + if (st.isEmpty()) { //st为空,表明无成功替换的内嵌规则 + + try { + + val obj = ctx.read(rule) //kotlin的Any型返回值不包含null ,删除赘余 ?: return result + + if (obj is List<*>) { + + for (o in obj) result.add(o.toString()) + + } else result.add(obj.toString()) + + } catch (ignored: Exception) { + } + + }else result.add(st) + + return result + + } else { + val results = ArrayList>() + for (rl in rules) { + val temp = getStringList(rl) + if (temp.isNotEmpty()) { + results.add(temp) + if (temp.isNotEmpty() && ruleAnalyzes.elementsType == "||") { + break + } + } + } + if (results.size > 0) { + if ("%%" == ruleAnalyzes.elementsType) { + for (i in results[0].indices) { + for (temp in results) { + if (i < temp.size) { + result.add(temp[i]) + } + } + } + } else { + for (temp in results) { + result.addAll(temp) + } + } + } + return result + } + } + + internal fun getObject(rule: String): Any { + return ctx.read(rule) + } + + internal fun getList(rule: String): ArrayList? { + val result = ArrayList() + if (rule.isEmpty()) return result + val ruleAnalyzes = RuleAnalyzer(rule) + val rules = ruleAnalyzes.splitRule("&&","||","%%") + if (rules.size == 1) { + ctx.let { + try { + return it.read>(rules[0]) + } catch (e: Exception) { + e.printStackTrace() + } + } + return null + } else { + val results = ArrayList>() + for (rl in rules) { + val temp = getList(rl) + if (temp != null && temp.isNotEmpty()) { + results.add(temp) + if (temp.isNotEmpty() && ruleAnalyzes.elementsType == "||") { + break + } + } + } + if (results.size > 0) { + if ("%%" == ruleAnalyzes.elementsType) { + for (i in 0 until results[0].size) { + for (temp in results) { + if (i < temp.size) { + temp[i]?.let { result.add(it) } + } + } + } + } else { + for (temp in results) { + result.addAll(temp) + } + } + } + } + return result + } + +} From 38f0f832ed3f928ff3e344bc9178e150bfd112de Mon Sep 17 00:00:00 2001 From: bushixuanqi <57338301+bushixuanqi@users.noreply.github.com> Date: Sun, 4 Jul 2021 02:55:10 +0800 Subject: [PATCH 04/12] Update AnalyzeByJSonPath.kt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 优化注释描述 --- .../java/io/legado/app/model/analyzeRule/AnalyzeByJSonPath.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSonPath.kt b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSonPath.kt index 63e02ec8c..b2704513a 100644 --- a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSonPath.kt +++ b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSonPath.kt @@ -25,7 +25,7 @@ class AnalyzeByJSonPath(json: Any) { /** * 改进解析方法 * 解决阅读”&&“、”||“与jsonPath支持的”&&“、”||“之间的冲突 - * 解决{$.rule}形式规则可能匹配错误的问题,旧规则用正则解析内容含‘}’的json文本时,用规则中的字段去匹配这种内容时,会匹配错误.现改用平衡嵌套方法解决这个问题 + * 解决{$.rule}形式规则可能匹配错误的问题,旧规则用正则解析内容含‘}’的json文本时,用规则中的字段去匹配这种内容会匹配错误.现改用平衡嵌套方法解决这个问题 * */ fun getString(rule: String): String? { if (rule.isEmpty()) return null From 464c8fe66eac74bb3cb8cd6b07b0a5e50c5b3411 Mon Sep 17 00:00:00 2001 From: bushixuanqi <57338301+bushixuanqi@users.noreply.github.com> Date: Sun, 4 Jul 2021 02:56:56 +0800 Subject: [PATCH 05/12] Update AnalyzeByJSoup.kt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修正一个错误 --- .../main/java/io/legado/app/model/analyzeRule/AnalyzeByJSoup.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSoup.kt b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSoup.kt index 6f45f9f21..81855fcbf 100644 --- a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSoup.kt +++ b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSoup.kt @@ -451,7 +451,7 @@ class AnalyzeByJSoup(doc: Any) { if (start == end || stepx >= len) { //两端相同,区间里只有一个数。或间隔过大,区间实际上仅有首位 - indexSet.add(stepx) + indexSet.add(start) continue } From 91f721e28c0a44a642eb260c5306d09624c9d69c Mon Sep 17 00:00:00 2001 From: bushixuanqi <57338301+bushixuanqi@users.noreply.github.com> Date: Sun, 4 Jul 2021 03:19:05 +0800 Subject: [PATCH 06/12] Update AnalyzeByJSoup.kt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 重置区间暂存列表,解决存在多个区间时的问题 --- .../main/java/io/legado/app/model/analyzeRule/AnalyzeByJSoup.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSoup.kt b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSoup.kt index 81855fcbf..112e85982 100644 --- a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSoup.kt +++ b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSoup.kt @@ -244,6 +244,8 @@ class AnalyzeByJSoup(doc: Any) { ) + curList.clear() //重置 + if(rl == '!'){ indexSet.split='!' do{ rl = rus[--len] } while (len > 0 && rl == ' ')//跳过所有空格 From a04e54543c229784581405fdba69f11d89ce0c07 Mon Sep 17 00:00:00 2001 From: bushixuanqi <57338301+bushixuanqi@users.noreply.github.com> Date: Sun, 4 Jul 2021 03:23:26 +0800 Subject: [PATCH 07/12] Update AnalyzeByJSoup.kt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 更改重置区间操作的位置,避免不必要的操作 --- .../java/io/legado/app/model/analyzeRule/AnalyzeByJSoup.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSoup.kt b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSoup.kt index 112e85982..1e9567578 100644 --- a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSoup.kt +++ b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSoup.kt @@ -244,8 +244,6 @@ class AnalyzeByJSoup(doc: Any) { ) - curList.clear() //重置 - if(rl == '!'){ indexSet.split='!' do{ rl = rus[--len] } while (len > 0 && rl == ' ')//跳过所有空格 @@ -256,6 +254,7 @@ class AnalyzeByJSoup(doc: Any) { } //遇到索引边界,返回结果 if(rl != ',') break //非索引结构,跳出 + curList.clear() //重置 } } From ad22929c3858adbe97eb36986fc41e131e99c84f Mon Sep 17 00:00:00 2001 From: bushixuanqi <57338301+bushixuanqi@users.noreply.github.com> Date: Sun, 4 Jul 2021 03:53:40 +0800 Subject: [PATCH 08/12] Update AnalyzeByJSoup.kt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 继续优化代码,避免不必要的操作 --- .../app/model/analyzeRule/AnalyzeByJSoup.kt | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSoup.kt b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSoup.kt index 1e9567578..4ce3be1bb 100644 --- a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSoup.kt +++ b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSoup.kt @@ -236,13 +236,16 @@ class AnalyzeByJSoup(doc: Any) { else -> { - indexSet.indexs.add( //压入以下值,为保证查找顺序,区间和单个索引都添加到同一集合 + //为保证查找顺序,区间和单个索引都添加到同一集合 + if(curList.isEmpty())indexSet.indexs.add(curInt!!) + else{ - if(curList.isEmpty()) curInt!! //区间为空,表明当前是单个索引,单个索引不能空 + //列表最后压入的是区间右端,若列表有两位则最先压入的是间隔 + indexSet.indexs.add( Triple(curInt, curList.last(), if(curList.size == 2) curList.first() else 1) ) - else Triple(curInt, curList.last(), if(curList.size == 2) curList.first() else 1) //否则为区间,列表最后压入的是区间右端,若列表有两位则最先压入了间隔 + curList.clear() //重置临时列表,避免影响到下个区间的处理 - ) + } if(rl == '!'){ indexSet.split='!' @@ -254,7 +257,6 @@ class AnalyzeByJSoup(doc: Any) { } //遇到索引边界,返回结果 if(rl != ',') break //非索引结构,跳出 - curList.clear() //重置 } } @@ -432,9 +434,9 @@ class AnalyzeByJSoup(doc: Any) { if(indexs.isEmpty())for (ix in lastIndexs downTo 0 ){ //indexs为空,表明是非[]式索引,集合是逆向遍历插入的,所以这里也逆向遍历,好还原顺序 - val it = indexDefault[ix] - if(it in 0 until len) indexSet.add(it) //将正数不越界的索引添加到集合 - else if(it < 0 && len >= -it) indexSet.add(it + len) //将负数不越界的索引添加到集合 + val it = indexDefault[ix] + if(it in 0 until len) indexSet.add(it) //将正数不越界的索引添加到集合 + else if(it < 0 && len >= -it) indexSet.add(it + len) //将负数不越界的索引添加到集合 }else for (ix in lastIndexs downTo 0 ){ //indexs不空,表明是[]式索引,集合是逆向遍历插入的,所以这里也逆向遍历,好还原顺序 From 9a00fb82daa75ad74354a2625621ebf19f3bd2f4 Mon Sep 17 00:00:00 2001 From: bushixuanqi <57338301+bushixuanqi@users.noreply.github.com> Date: Sun, 4 Jul 2021 14:30:13 +0800 Subject: [PATCH 09/12] Update RuleAnalyzer.kt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 简化部分规则,调整压入切分出的规则时的判断顺序,避免重复压入 --- .../app/model/analyzeRule/RuleAnalyzer.kt | 144 +++++++++--------- 1 file changed, 75 insertions(+), 69 deletions(-) diff --git a/app/src/main/java/io/legado/app/model/analyzeRule/RuleAnalyzer.kt b/app/src/main/java/io/legado/app/model/analyzeRule/RuleAnalyzer.kt index 73a861acf..09129de7a 100644 --- a/app/src/main/java/io/legado/app/model/analyzeRule/RuleAnalyzer.kt +++ b/app/src/main/java/io/legado/app/model/analyzeRule/RuleAnalyzer.kt @@ -8,7 +8,6 @@ class RuleAnalyzer(data: String) { private var pos = 0 //处理到的位置 private var start = 0 //每次处理字段的开始 - private var end:Int = queue.length //每次处理字段的终点 private var step:Int = 0 //分割字符的长度 var elementsType = "" @@ -29,7 +28,7 @@ class RuleAnalyzer(data: String) { } //剩余字串 - fun remainingString(): String { + private fun remainingString(): String { start = pos pos = queue.length return queue.substring(start) @@ -82,69 +81,73 @@ class RuleAnalyzer(data: String) { return queue.regionMatches(pos, seq, 0, seq.length, ignoreCase = true) } - /** - * 测试下个字符是否与序列中相应位置的字符相等。 - * @param seq :被检查的字符列表 - * @return 相等就为 true ,不相等则为 false - */ - fun matchesAny(vararg seq: Char): Boolean { - if (isEmpty) return false - for (c in seq) { - if (queue[pos] == c) { - return true - } - } - return false - } - - /** - * 测试下个字符(串)是否与参数列表里的序列存在匹配。 不区分大小写。 - * @param seq :被不区分大小写检查的字符串列表 - * @return 只要匹配就为 true ,没有匹配则为 false - */ - fun matchesAny(vararg seq: String): Boolean { - for (s in seq) { - if (matches(s)) { - step = s.length - return true - } - } - return false - } - /** * 从剩余字串中拉出一个字符串,直到但不包括匹配序列,或剩余字串用完。 * @param seq :分隔字符 **区分大小写** * @return 是否找到相应字段。 */ fun consumeTo(seq: String,setStartPos:Boolean = true): Boolean { + if(setStartPos)start = pos //将处理到的位置设置为规则起点 val offset = queue.indexOf(seq, pos) return if (offset != -1) { pos = offset true } else false + + } + + /** + * 从剩余字串中拉出一个字符串,直到且包括匹配序列(匹配参数列表中一项即为匹配),或剩余字串用完。 + * @param seq 匹配字符串序列 + * @return 成功返回true并推移pos,失败返回fasle而不推移pos + */ + fun consumeToAny(vararg seq:String): Boolean { + + start = pos + + while (!isEmpty) { + + for (s in seq) { + if (matches(s)) { + step = s.length //间隔数 + return true //匹配就返回 true + } + } + + pos++ //逐个试探 + } + + pos = start //匹配失败,位置回退 + + return false } /** * 从剩余字串中拉出一个字符串,直到但不包括匹配序列(匹配参数列表中一项即为匹配),或剩余字串用完。 - * @param f 消费函数,返回true表示消费,fasle表示不消费 - * @param setStartPos 设置开始消费位置 - * @return 消耗的字符串 + * @param seq 匹配字符序列 + * @return 匹配到的位置 */ - fun consumeToAny(setStartPos:Boolean = true, f:()->Boolean,): Boolean { - if(setStartPos)start = pos //将处理到的位置设置为规则起点 - while (!isEmpty && !f()) { - pos++ + private fun findToAny(vararg seq:Char): Int { + + for (s in seq){ + + val offset = queue.indexOf(s, pos) + + if (offset != -1) return offset //只要匹配到,就返回相应位置 + } - return !isEmpty + + return -1 } //其中js只要符合语法,就不用避开任何阅读关键字,自由发挥 fun chompJsBalanced(f: ((Char) -> Boolean?) = { - if ( it == '{' )true //开始嵌套一层 - else if ( it == '}') false //闭合一层嵌套 - else null + when (it) { + '{' -> true //开始嵌套一层 + '}' -> false //闭合一层嵌套 + else -> null + } } ): Boolean { start = pos var depth = 0 //嵌套深度 @@ -178,20 +181,20 @@ class RuleAnalyzer(data: String) { } else if(regex && c == '/') { //正则的终点或[]平衡 - if(c == '/')regex = false//匹配正则终点 - - //为了保证当open为( 且 close 为 )时,正则中[(]或[)]的合法性。故对[]这对在任何规则中都平衡的成对符号做匹配。 - // 注:正则里[(]、[)]、[{]、[}]都是合法的,所以只有[]必须平衡。 + when (c) { + '/' -> regex = false//匹配正则终点 - else if ( c == '[' )bracketsDepth++ //开始嵌套一层[] - else if ( c== ']') bracketsDepth-- //闭合一层嵌套[] + //为了保证当open为( 且 close 为 )时,正则中[(]或[)]的合法性。故对[]这对在任何规则中都平衡的成对符号做匹配。 + // 注:正则里[(]、[)]、[{]、[}]都是合法的,所以只有[]必须平衡。 + '[' -> bracketsDepth++ //开始嵌套一层[] + ']' -> bracketsDepth-- //闭合一层嵌套[] + } } if (commits || commit || regex || inSingleQuote || inDoubleQuote || inOtherQuote) continue //语法单元未匹配结束,直接进入下个循环 - val fn = f(c) - if (fn == null) continue + val fn = f(c) ?: continue if (fn) depth++ else depth-- //嵌套或者闭合 }else { //转义字符 @@ -233,8 +236,7 @@ class RuleAnalyzer(data: String) { if ( c == open )depth++ //开始嵌套一层 else if ( c== close) depth-- //闭合一层嵌套 else if(depth == 0 && f != null) { //处于默认嵌套中的非默认字符不需要平衡,仅depth为0时默认嵌套全部闭合,此字符才进行嵌套 - val fn = f(c) - if (fn == null) continue + val fn = f(c) ?: continue if (fn) otherDepth++ else otherDepth-- } @@ -257,24 +259,28 @@ class RuleAnalyzer(data: String) { */ tailrec fun splitRule(vararg split: String): Array{ //首段匹配,elementsType为空 - if (!consumeToAny { matchesAny(* split) }) return arrayOf(queue) //未找到分隔符 + if(split.size == 1) { + elementsType = split[0] //设置分割字串 + step = elementsType.length //设置分隔符长度 + return splitRule(arrayOf()) //仅一个分隔字串时,直接二段解析更快 + }else if (!consumeToAny(* split)) return arrayOf(queue) //未找到分隔符 - end = pos - val st = if( consumeToAny(false){ matchesAny( '(','[' ) } )pos else -1 //查找筛选器 - pos = end + val st = findToAny( '(','[' ) //查找筛选器 if(st == -1) { var rule = arrayOf(queue.substring(0, pos)) //压入分隔的首段规则到数组 + elementsType = queue.substring(pos, pos + step) //设置组合类型 pos += step //跳过分隔符 - elementsType = queue.substring(pos - step, pos) //设置组合类型 - while (consumeToAny { matchesAny(* split) }) { //循环切分规则压入数组 + while (consumeToAny(* split)) { //循环切分规则压入数组 rule += queue.substring(start, pos) pos += step //跳过分隔符 } - rule+= queue.substring(start) //将剩余字段压入数组末尾 + + rule += queue.substring(pos) //将剩余字段压入数组末尾 + return rule } @@ -282,14 +288,16 @@ class RuleAnalyzer(data: String) { var rule = arrayOf(queue.substring(0, pos)) //压入分隔的首段规则到数组 + elementsType = queue.substring(pos, pos + step) //设置组合类型 pos += step //跳过分隔符 - elementsType = queue.substring(pos - step, pos) //设置组合类型 - while (pos < st && consumeToAny { matchesAny( * split ) }) { - rule += queue.substring(start, pos) //循环切分规则压入数组 + while (consumeToAny( * split ) && pos < st ) { //循环切分规则压入数组 + rule += queue.substring(start, pos) pos += step //跳过分隔符 } + rule + }else null pos = st //位置推移到筛选器处 @@ -316,9 +324,7 @@ class RuleAnalyzer(data: String) { if (!consumeTo(elementsType,false)) return rules + queue.substring(start) //此处consumeTo(...)开始位置不是规则的开始位置,start沿用上次设置 - end = pos - val st = if( consumeToAny(false){ matchesAny( '(','[' ) } )pos else -1 //查找筛选器 - pos = end + val st = findToAny( '(','[' ) //查找筛选器 if(st == -1) { var rule = rules + queue.substring(start, pos) //压入本次分隔的首段规则到数组 @@ -327,14 +333,14 @@ class RuleAnalyzer(data: String) { rule += queue.substring(start, pos) pos += step //跳过分隔符 } - rule += queue.substring(start) //将剩余字段压入数组末尾 + rule += queue.substring(pos) //将剩余字段压入数组末尾 return rule } val rule = if(st > pos ){//先匹配到st1pos,表明"&&","||"不在选择器中,将选择器前"&&","||"分隔的字段依次压入数组 var rule = rules + queue.substring(start, pos) //压入本次分隔的首段规则到数组 pos += step //跳过分隔符 - while (pos < st && consumeTo(elementsType)) { //循环切分规则压入数组 + while (consumeTo(elementsType) && pos < st) { //循环切分规则压入数组 rule += queue.substring(start, pos) pos += step //跳过分隔符 } @@ -512,4 +518,4 @@ class RuleAnalyzer(data: String) { val splitListDefault = arrayOf("-",".","!","@","@@") } -} \ No newline at end of file +} From d8a83f9e156a9a238d644d6df9a1abfd5050209f Mon Sep 17 00:00:00 2001 From: bushixuanqi <57338301+bushixuanqi@users.noreply.github.com> Date: Sun, 4 Jul 2021 14:35:07 +0800 Subject: [PATCH 10/12] Update RuleAnalyzer.kt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 优化注释描述 --- .../java/io/legado/app/model/analyzeRule/RuleAnalyzer.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/io/legado/app/model/analyzeRule/RuleAnalyzer.kt b/app/src/main/java/io/legado/app/model/analyzeRule/RuleAnalyzer.kt index 09129de7a..2bcf3555f 100644 --- a/app/src/main/java/io/legado/app/model/analyzeRule/RuleAnalyzer.kt +++ b/app/src/main/java/io/legado/app/model/analyzeRule/RuleAnalyzer.kt @@ -255,7 +255,7 @@ class RuleAnalyzer(data: String) { /** * 不用正则,不到最后不切片也不用中间变量存储,只在序列中标记当前查找字段的开头结尾,到返回时才切片,高效快速准确切割规则 - * 解决jsonPath自带的"&&"和"||"与阅读的规则冲突,以及规则正则或字符串中包含"&&"或"||"或"%%"而导致的冲突 + * 解决jsonPath自带的"&&"和"||"与阅读的规则冲突,以及规则正则或字符串中包含"&&"、"||"、"%%"、"@"导致的冲突 */ tailrec fun splitRule(vararg split: String): Array{ //首段匹配,elementsType为空 @@ -284,7 +284,7 @@ class RuleAnalyzer(data: String) { return rule } - val rule = if(st >pos ){ //先匹配到st1pos,表明"&&","||"不在选择器中,将选择器前"&&","||"分隔的字段依次压入数组 + val rule = if(st >pos ){ //先匹配到st1pos,表明分隔字串不在选择器中,将选择器前分隔字串分隔的字段依次压入数组 var rule = arrayOf(queue.substring(0, pos)) //压入分隔的首段规则到数组 @@ -337,7 +337,7 @@ class RuleAnalyzer(data: String) { return rule } - val rule = if(st > pos ){//先匹配到st1pos,表明"&&","||"不在选择器中,将选择器前"&&","||"分隔的字段依次压入数组 + val rule = if(st > pos ){//先匹配到st1pos,表明分隔字串不在选择器中,将选择器前分隔字串分隔的字段依次压入数组 var rule = rules + queue.substring(start, pos) //压入本次分隔的首段规则到数组 pos += step //跳过分隔符 while (consumeTo(elementsType) && pos < st) { //循环切分规则压入数组 From c9f2071e004c41dc1345995102dc573adf9a0cfa Mon Sep 17 00:00:00 2001 From: bushixuanqi <57338301+bushixuanqi@users.noreply.github.com> Date: Sun, 4 Jul 2021 14:37:37 +0800 Subject: [PATCH 11/12] Update AnalyzeByJSoup.kt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 允许索引作为首规则,此时相对于children。 head@[1]@text 与 head@children[1]@text 等价 --- .../io/legado/app/model/analyzeRule/AnalyzeByJSoup.kt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSoup.kt b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSoup.kt index 4ce3be1bb..be1615a46 100644 --- a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSoup.kt +++ b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeByJSoup.kt @@ -213,7 +213,7 @@ class AnalyzeByJSoup(doc: Any) { val curList = mutableListOf() //当前数字区间 var l = "" //暂存数字字符串 - val head = rus[rus.length-1] == ']' //是否为常规索引写法 + val head = rus.last() == ']' //是否为常规索引写法 if(head){ //常规索引写法[index...] @@ -236,7 +236,7 @@ class AnalyzeByJSoup(doc: Any) { else -> { - //为保证查找顺序,区间和单个索引都添加到同一集合 + //为保证查找顺序,区间和单个索引都添加到同一集合 if(curList.isEmpty())indexSet.indexs.add(curInt!!) else{ @@ -265,7 +265,7 @@ class AnalyzeByJSoup(doc: Any) { curMinus = false //重置 } } - } else while (len --> 1) { //阅读原本写法,逆向遍历,至少两位前置字符,如 p. + } else while (len --> 0) { //阅读原本写法,逆向遍历,至少两位前置字符,如 . val rl = rus[len] if (rl == ' ') continue //跳过空格 @@ -314,8 +314,9 @@ class AnalyzeByJSoup(doc: Any) { val rules = ruleStr.split(".") elements.addAll( - when (rules[0]) { - "children" -> temp.children() + if(ruleStr.isEmpty()) temp.children() //允许索引直接作为根元素,此时前置规则为空,效果与children相同 + else when (rules[0]) { + "children" -> temp.children() //允许索引直接作为根元素,此时前置规则为空,效果与children相同 "class" -> temp.getElementsByClass(rules[1]) "tag" -> temp.getElementsByTag(rules[1]) "id" -> Collector.collect(Evaluator.Id(rules[1]), temp) From 0978ff83fd4c059c1d6b2bbebd91794f18536b6a Mon Sep 17 00:00:00 2001 From: bushixuanqi <57338301+bushixuanqi@users.noreply.github.com> Date: Sun, 4 Jul 2021 15:00:03 +0800 Subject: [PATCH 12/12] Update RuleAnalyzer.kt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修正注释描述 --- .../java/io/legado/app/model/analyzeRule/RuleAnalyzer.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/io/legado/app/model/analyzeRule/RuleAnalyzer.kt b/app/src/main/java/io/legado/app/model/analyzeRule/RuleAnalyzer.kt index 2bcf3555f..50d91ba15 100644 --- a/app/src/main/java/io/legado/app/model/analyzeRule/RuleAnalyzer.kt +++ b/app/src/main/java/io/legado/app/model/analyzeRule/RuleAnalyzer.kt @@ -98,9 +98,9 @@ class RuleAnalyzer(data: String) { } /** - * 从剩余字串中拉出一个字符串,直到且包括匹配序列(匹配参数列表中一项即为匹配),或剩余字串用完。 + * 从剩余字串中拉出一个字符串,直到但不包括匹配序列(匹配参数列表中一项即为匹配),或剩余字串用完。 * @param seq 匹配字符串序列 - * @return 成功返回true并推移pos,失败返回fasle而不推移pos + * @return 成功返回true并设置间隔,失败则直接返回fasle */ fun consumeToAny(vararg seq:String): Boolean { @@ -126,7 +126,7 @@ class RuleAnalyzer(data: String) { /** * 从剩余字串中拉出一个字符串,直到但不包括匹配序列(匹配参数列表中一项即为匹配),或剩余字串用完。 * @param seq 匹配字符序列 - * @return 匹配到的位置 + * @return 返回匹配位置 */ private fun findToAny(vararg seq:Char): Int {