pull/32/head
parent
bf0f6438f9
commit
5437bf824a
@ -0,0 +1,435 @@ |
|||||||
|
package io.legado.app.model.analyzeRule |
||||||
|
|
||||||
|
import android.text.TextUtils.isEmpty |
||||||
|
import android.text.TextUtils.join |
||||||
|
import io.legado.app.utils.startWithIgnoreCase |
||||||
|
import org.jsoup.Jsoup |
||||||
|
import org.jsoup.nodes.Element |
||||||
|
import org.jsoup.select.Collector |
||||||
|
import org.jsoup.select.Elements |
||||||
|
import org.jsoup.select.Evaluator |
||||||
|
import org.seimicrawler.xpath.JXNode |
||||||
|
import java.util.* |
||||||
|
|
||||||
|
/** |
||||||
|
* Created by GKF on 2018/1/25. |
||||||
|
* 书源规则解析 |
||||||
|
*/ |
||||||
|
|
||||||
|
class AnalyzeByJSoup { |
||||||
|
private var element: Element? = null |
||||||
|
|
||||||
|
fun parse(doc: Any): AnalyzeByJSoup { |
||||||
|
if (doc is Element) { |
||||||
|
element = doc |
||||||
|
} else if (doc is JXNode) { |
||||||
|
if (doc.isElement) { |
||||||
|
element = doc.asElement() |
||||||
|
} else { |
||||||
|
element = Jsoup.parse(doc.value().toString()) |
||||||
|
} |
||||||
|
} else { |
||||||
|
element = Jsoup.parse(doc.toString()) |
||||||
|
} |
||||||
|
return this |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取列表 |
||||||
|
*/ |
||||||
|
internal fun getElements(rule: String): Elements { |
||||||
|
return getElements(element, rule) |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 合并内容列表,得到内容 |
||||||
|
*/ |
||||||
|
internal fun getString(ruleStr: String): String? { |
||||||
|
if (isEmpty(ruleStr)) { |
||||||
|
return null |
||||||
|
} |
||||||
|
val textS = getStringList(ruleStr) |
||||||
|
return if (textS.isEmpty()) { |
||||||
|
null |
||||||
|
} else join("\n", textS).trim { it <= ' ' } |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取一个字符串 |
||||||
|
*/ |
||||||
|
internal fun getString0(ruleStr: String): String { |
||||||
|
val urlList = getStringList(ruleStr) |
||||||
|
return if (urlList.isNotEmpty()) { |
||||||
|
urlList[0] |
||||||
|
} else "" |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取所有内容列表 |
||||||
|
*/ |
||||||
|
internal fun getStringList(ruleStr: String): List<String> { |
||||||
|
val textS = ArrayList<String>() |
||||||
|
if (isEmpty(ruleStr)) { |
||||||
|
return textS |
||||||
|
} |
||||||
|
//拆分规则 |
||||||
|
val sourceRule = SourceRule(ruleStr) |
||||||
|
if (isEmpty(sourceRule.elementsRule)) { |
||||||
|
textS.add(element!!.data()) |
||||||
|
} else { |
||||||
|
val elementsType: String |
||||||
|
val ruleStrS: Array<String> |
||||||
|
when { |
||||||
|
sourceRule.elementsRule.contains("&") -> { |
||||||
|
elementsType = "&" |
||||||
|
ruleStrS = |
||||||
|
sourceRule.elementsRule.split("&+".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() |
||||||
|
} |
||||||
|
sourceRule.elementsRule.contains("%%") -> { |
||||||
|
elementsType = "%" |
||||||
|
ruleStrS = |
||||||
|
sourceRule.elementsRule.split("%%".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() |
||||||
|
} |
||||||
|
else -> { |
||||||
|
elementsType = "|" |
||||||
|
ruleStrS = if (sourceRule.isCss) { |
||||||
|
sourceRule.elementsRule.split("\\|\\|".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() |
||||||
|
} else { |
||||||
|
sourceRule.elementsRule.split("\\|+".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
val results = ArrayList<List<String>>() |
||||||
|
for (ruleStrX in ruleStrS) { |
||||||
|
val temp: List<String>? |
||||||
|
temp = if (sourceRule.isCss) { |
||||||
|
val lastIndex = ruleStrX.lastIndexOf('@') |
||||||
|
getResultLast( |
||||||
|
element!!.select(ruleStrX.substring(0, lastIndex)), |
||||||
|
ruleStrX.substring(lastIndex + 1) |
||||||
|
) |
||||||
|
} else { |
||||||
|
getResultList(ruleStrX) |
||||||
|
} |
||||||
|
if (temp != null && temp.isNotEmpty()) { |
||||||
|
results.add(temp) |
||||||
|
if (results.isNotEmpty() && elementsType == "|") { |
||||||
|
break |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if (results.size > 0) { |
||||||
|
if ("%" == elementsType) { |
||||||
|
for (i in 0 until results[0].size) { |
||||||
|
for (temp in results) { |
||||||
|
if (i < temp.size) { |
||||||
|
textS.add(temp[i]) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} else { |
||||||
|
for (temp in results) { |
||||||
|
textS.addAll(temp) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if (!isEmpty(sourceRule.replaceRegex)) { |
||||||
|
val tempList = ArrayList(textS) |
||||||
|
textS.clear() |
||||||
|
for (text in tempList) { |
||||||
|
val tmpText = text.replace(sourceRule.replaceRegex.toRegex(), sourceRule.replacement) |
||||||
|
if (tmpText.isNotEmpty()) { |
||||||
|
textS.add(tmpText) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return textS |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取Elements |
||||||
|
*/ |
||||||
|
private fun getElements(temp: Element?, rule: String): Elements { |
||||||
|
val elements = Elements() |
||||||
|
if (temp == null || isEmpty(rule)) { |
||||||
|
return elements |
||||||
|
} |
||||||
|
val sourceRule = SourceRule(rule) |
||||||
|
val elementsType: String |
||||||
|
val ruleStrS: Array<String> |
||||||
|
when { |
||||||
|
sourceRule.elementsRule.contains("&") -> { |
||||||
|
elementsType = "&" |
||||||
|
ruleStrS = sourceRule.elementsRule.split("&+".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() |
||||||
|
} |
||||||
|
sourceRule.elementsRule.contains("%") -> { |
||||||
|
elementsType = "%" |
||||||
|
ruleStrS = sourceRule.elementsRule.split("%+".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() |
||||||
|
} |
||||||
|
else -> { |
||||||
|
elementsType = "|" |
||||||
|
ruleStrS = if (sourceRule.isCss) { |
||||||
|
sourceRule.elementsRule.split("\\|\\|".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() |
||||||
|
} else { |
||||||
|
sourceRule.elementsRule.split("\\|+".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
val elementsList = ArrayList<Elements>() |
||||||
|
if (sourceRule.isCss) { |
||||||
|
for (ruleStr in ruleStrS) { |
||||||
|
val tempS = temp.select(ruleStr) |
||||||
|
elementsList.add(tempS) |
||||||
|
if (tempS.size > 0 && elementsType == "|") { |
||||||
|
break |
||||||
|
} |
||||||
|
} |
||||||
|
} else { |
||||||
|
for (ruleStr in ruleStrS) { |
||||||
|
val tempS = getElementsSingle(temp, ruleStr) |
||||||
|
elementsList.add(tempS) |
||||||
|
if (tempS.size > 0 && elementsType == "|") { |
||||||
|
break |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if (elementsList.size > 0) { |
||||||
|
if ("%" == elementsType) { |
||||||
|
for (i in 0 until elementsList[0].size) { |
||||||
|
for (es in elementsList) { |
||||||
|
if (i < es.size) { |
||||||
|
elements.add(es[i]) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} else { |
||||||
|
for (es in elementsList) { |
||||||
|
elements.addAll(es) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return elements |
||||||
|
} |
||||||
|
|
||||||
|
private fun filterElements(elements: Elements, rules: Array<String>?): Elements { |
||||||
|
if (rules == null || rules.size < 2) return elements |
||||||
|
val selectedEls = Elements() |
||||||
|
for (ele in elements) { |
||||||
|
var isOk = false |
||||||
|
when (rules[0]) { |
||||||
|
"class" -> isOk = ele.getElementsByClass(rules[1]).size > 0 |
||||||
|
"id" -> isOk = ele.getElementById(rules[1]) != null |
||||||
|
"tag" -> isOk = ele.getElementsByTag(rules[1]).size > 0 |
||||||
|
"text" -> isOk = ele.getElementsContainingOwnText(rules[1]).size > 0 |
||||||
|
} |
||||||
|
if (isOk) { |
||||||
|
selectedEls.add(ele) |
||||||
|
} |
||||||
|
} |
||||||
|
return selectedEls |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取Elements按照一个规则 |
||||||
|
*/ |
||||||
|
private fun getElementsSingle(temp: Element, rule: String): Elements { |
||||||
|
val elements = Elements() |
||||||
|
try { |
||||||
|
val rs = rule.trim { it <= ' ' }.split("@".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() |
||||||
|
if (rs.size > 1) { |
||||||
|
elements.add(temp) |
||||||
|
for (rl in rs) { |
||||||
|
val es = Elements() |
||||||
|
for (et in elements) { |
||||||
|
es.addAll(getElements(et, rl)) |
||||||
|
} |
||||||
|
elements.clear() |
||||||
|
elements.addAll(es) |
||||||
|
} |
||||||
|
} else { |
||||||
|
val rulePcx = rule.split("!".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() |
||||||
|
val rulePc = |
||||||
|
rulePcx[0].trim { it <= ' ' }.split(">".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() |
||||||
|
val rules = |
||||||
|
rulePc[0].trim { it <= ' ' }.split("\\.".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() |
||||||
|
var filterRules: Array<String>? = null |
||||||
|
var needFilterElements = rulePc.size > 1 && !isEmpty(rulePc[1].trim { it <= ' ' }) |
||||||
|
if (needFilterElements) { |
||||||
|
filterRules = rulePc[1].trim { it <= ' ' }.split("\\.".toRegex()).dropLastWhile { it.isEmpty() } |
||||||
|
.toTypedArray() |
||||||
|
filterRules[0] = filterRules[0].trim { it <= ' ' } |
||||||
|
val validKeys = listOf("class", "id", "tag", "text") |
||||||
|
if (filterRules.size < 2 || !validKeys.contains(filterRules[0]) || isEmpty(filterRules[1].trim { it <= ' ' })) { |
||||||
|
needFilterElements = false |
||||||
|
} |
||||||
|
filterRules[1] = filterRules[1].trim { it <= ' ' } |
||||||
|
} |
||||||
|
when (rules[0]) { |
||||||
|
"children" -> { |
||||||
|
var children = temp.children() |
||||||
|
if (needFilterElements) |
||||||
|
children = filterElements(children, filterRules) |
||||||
|
elements.addAll(children) |
||||||
|
} |
||||||
|
"class" -> { |
||||||
|
var elementsByClass = temp.getElementsByClass(rules[1]) |
||||||
|
if (rules.size == 3) { |
||||||
|
val index = Integer.parseInt(rules[2]) |
||||||
|
if (index < 0) { |
||||||
|
elements.add(elementsByClass[elementsByClass.size + index]) |
||||||
|
} else { |
||||||
|
elements.add(elementsByClass[index]) |
||||||
|
} |
||||||
|
} else { |
||||||
|
if (needFilterElements) |
||||||
|
elementsByClass = filterElements(elementsByClass, filterRules) |
||||||
|
elements.addAll(elementsByClass) |
||||||
|
} |
||||||
|
} |
||||||
|
"tag" -> { |
||||||
|
var elementsByTag = temp.getElementsByTag(rules[1]) |
||||||
|
if (rules.size == 3) { |
||||||
|
val index = Integer.parseInt(rules[2]) |
||||||
|
if (index < 0) { |
||||||
|
elements.add(elementsByTag[elementsByTag.size + index]) |
||||||
|
} else { |
||||||
|
elements.add(elementsByTag[index]) |
||||||
|
} |
||||||
|
} else { |
||||||
|
if (needFilterElements) |
||||||
|
elementsByTag = filterElements(elementsByTag, filterRules) |
||||||
|
elements.addAll(elementsByTag) |
||||||
|
} |
||||||
|
} |
||||||
|
"id" -> { |
||||||
|
var elementsById = Collector.collect(Evaluator.Id(rules[1]), temp) |
||||||
|
if (rules.size == 3) { |
||||||
|
val index = Integer.parseInt(rules[2]) |
||||||
|
if (index < 0) { |
||||||
|
elements.add(elementsById[elementsById.size + index]) |
||||||
|
} else { |
||||||
|
elements.add(elementsById[index]) |
||||||
|
} |
||||||
|
} else { |
||||||
|
if (needFilterElements) |
||||||
|
elementsById = filterElements(elementsById, filterRules) |
||||||
|
elements.addAll(elementsById) |
||||||
|
} |
||||||
|
} |
||||||
|
"text" -> { |
||||||
|
var elementsByText = temp.getElementsContainingOwnText(rules[1]) |
||||||
|
if (needFilterElements) |
||||||
|
elementsByText = filterElements(elementsByText, filterRules) |
||||||
|
elements.addAll(elementsByText) |
||||||
|
} |
||||||
|
else -> elements.addAll(temp.select(rulePcx[0])) |
||||||
|
} |
||||||
|
if (rulePcx.size > 1) { |
||||||
|
val rulePcs = rulePcx[1].split(":".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() |
||||||
|
for (pc in rulePcs) { |
||||||
|
val pcInt = Integer.parseInt(pc) |
||||||
|
if (pcInt < 0 && elements.size + pcInt >= 0) { |
||||||
|
elements[elements.size + pcInt] = null |
||||||
|
} else if (Integer.parseInt(pc) < elements.size) { |
||||||
|
elements[Integer.parseInt(pc)] = null |
||||||
|
} |
||||||
|
} |
||||||
|
val es = Elements() |
||||||
|
es.add(null) |
||||||
|
elements.removeAll(es) |
||||||
|
} |
||||||
|
} |
||||||
|
} catch (ignore: Exception) { |
||||||
|
} |
||||||
|
|
||||||
|
return elements |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取内容列表 |
||||||
|
*/ |
||||||
|
private fun getResultList(ruleStr: String): List<String>? { |
||||||
|
if (isEmpty(ruleStr)) { |
||||||
|
return null |
||||||
|
} |
||||||
|
var elements = Elements() |
||||||
|
elements.add(element) |
||||||
|
val rules = ruleStr.split("@".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() |
||||||
|
for (i in 0 until rules.size - 1) { |
||||||
|
val es = Elements() |
||||||
|
for (elt in elements) { |
||||||
|
es.addAll(getElementsSingle(elt, rules[i])) |
||||||
|
} |
||||||
|
elements.clear() |
||||||
|
elements = es |
||||||
|
} |
||||||
|
return if (elements.isEmpty()) { |
||||||
|
null |
||||||
|
} else getResultLast(elements, rules[rules.size - 1]) |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 根据最后一个规则获取内容 |
||||||
|
*/ |
||||||
|
private fun getResultLast(elements: Elements, lastRule: String): List<String> { |
||||||
|
val textS = ArrayList<String>() |
||||||
|
try { |
||||||
|
when (lastRule) { |
||||||
|
"text" -> for (element in elements) { |
||||||
|
val text = element.text() |
||||||
|
textS.add(text) |
||||||
|
} |
||||||
|
"textNodes" -> for (element in elements) { |
||||||
|
val contentEs = element.textNodes() |
||||||
|
for (i in contentEs.indices) { |
||||||
|
val temp = contentEs[i].text().trim { it <= ' ' } |
||||||
|
if (!isEmpty(temp)) { |
||||||
|
textS.add(temp) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
"ownText", "html" -> { |
||||||
|
elements.select("script").remove() |
||||||
|
val html = elements.html() |
||||||
|
textS.add(html) |
||||||
|
} |
||||||
|
else -> for (element in elements) { |
||||||
|
val url = element.attr(lastRule) |
||||||
|
if (!isEmpty(url) && !textS.contains(url)) { |
||||||
|
textS.add(url) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} catch (ignore: Exception) { |
||||||
|
} |
||||||
|
|
||||||
|
return textS |
||||||
|
} |
||||||
|
|
||||||
|
internal inner class SourceRule(ruleStr: String) { |
||||||
|
var isCss = false |
||||||
|
var elementsRule: String |
||||||
|
var replaceRegex = "" |
||||||
|
var replacement = "" |
||||||
|
|
||||||
|
init { |
||||||
|
if (startWithIgnoreCase(ruleStr, "@CSS:")) { |
||||||
|
isCss = true |
||||||
|
elementsRule = ruleStr.substring(5).trim { it <= ' ' } |
||||||
|
} else { |
||||||
|
val ruleStrS: Array<String> = |
||||||
|
ruleStr.trim { it <= ' ' }.split("#".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() |
||||||
|
//分离正则表达式 |
||||||
|
elementsRule = ruleStrS[0] |
||||||
|
if (ruleStrS.size > 1) { |
||||||
|
replaceRegex = ruleStrS[1] |
||||||
|
} |
||||||
|
if (ruleStrS.size > 2) { |
||||||
|
replacement = ruleStrS[2] |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,160 @@ |
|||||||
|
package io.legado.app.model.analyzeRule |
||||||
|
|
||||||
|
import android.text.TextUtils |
||||||
|
import org.jsoup.nodes.Document |
||||||
|
import org.seimicrawler.xpath.JXDocument |
||||||
|
import org.seimicrawler.xpath.JXNode |
||||||
|
import java.util.* |
||||||
|
|
||||||
|
class AnalyzeByXPath { |
||||||
|
private var jxDocument: JXDocument? = null |
||||||
|
|
||||||
|
fun parse(doc: Any): AnalyzeByXPath { |
||||||
|
if (doc is Document) { |
||||||
|
jxDocument = JXDocument.create(doc) |
||||||
|
} else { |
||||||
|
var html = doc.toString() |
||||||
|
// 给表格标签添加完整的框架结构,否则会丢失表格标签;html标准不允许表格标签独立在table之外 |
||||||
|
if (html.endsWith("</td>")) { |
||||||
|
html = String.format("<tr>%s</tr>", html) |
||||||
|
} |
||||||
|
if (html.endsWith("</tr>") || html.endsWith("</tbody>")) { |
||||||
|
html = String.format("<table>%s</table>", html) |
||||||
|
} |
||||||
|
jxDocument = JXDocument.create(html) |
||||||
|
} |
||||||
|
return this |
||||||
|
} |
||||||
|
|
||||||
|
internal fun getElements(xPath: String): List<JXNode>? { |
||||||
|
if (TextUtils.isEmpty(xPath)) { |
||||||
|
return null |
||||||
|
} |
||||||
|
val jxNodes = ArrayList<JXNode>() |
||||||
|
val elementsType: String |
||||||
|
val rules: Array<String> |
||||||
|
if (xPath.contains("&&")) { |
||||||
|
rules = xPath.split("&&".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() |
||||||
|
elementsType = "&" |
||||||
|
} else if (xPath.contains("%%")) { |
||||||
|
rules = xPath.split("%%".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() |
||||||
|
elementsType = "%" |
||||||
|
} else { |
||||||
|
rules = xPath.split("\\|\\|".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() |
||||||
|
elementsType = "|" |
||||||
|
} |
||||||
|
if (rules.size == 1) { |
||||||
|
return jxDocument!!.selN(rules[0]) |
||||||
|
} else { |
||||||
|
val results = ArrayList<List<JXNode>>() |
||||||
|
for (rl in rules) { |
||||||
|
val temp = getElements(rl) |
||||||
|
if (temp != null && temp.isNotEmpty()) { |
||||||
|
results.add(temp) |
||||||
|
if (temp.isNotEmpty() && elementsType == "|") { |
||||||
|
break |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if (results.size > 0) { |
||||||
|
if ("%" == elementsType) { |
||||||
|
for (i in 0 until results[0].size) { |
||||||
|
for (temp in results) { |
||||||
|
if (i < temp.size) { |
||||||
|
jxNodes.add(temp[i]) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} else { |
||||||
|
for (temp in results) { |
||||||
|
jxNodes.addAll(temp) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return jxNodes |
||||||
|
} |
||||||
|
|
||||||
|
internal fun getStringList(xPath: String): List<String> { |
||||||
|
val result = ArrayList<String>() |
||||||
|
val elementsType: String |
||||||
|
val rules: Array<String> |
||||||
|
if (xPath.contains("&&")) { |
||||||
|
rules = xPath.split("&&".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() |
||||||
|
elementsType = "&" |
||||||
|
} else if (xPath.contains("%%")) { |
||||||
|
rules = xPath.split("%%".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() |
||||||
|
elementsType = "%" |
||||||
|
} else { |
||||||
|
rules = xPath.split("\\|\\|".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() |
||||||
|
elementsType = "|" |
||||||
|
} |
||||||
|
if (rules.size == 1) { |
||||||
|
val jxNodes = jxDocument!!.selN(xPath) |
||||||
|
for (jxNode in jxNodes) { |
||||||
|
/*if(jxNode.isString()){ |
||||||
|
result.add(String.valueOf(jxNode)); |
||||||
|
}*/ |
||||||
|
result.add(jxNode.toString()) |
||||||
|
} |
||||||
|
return result |
||||||
|
} else { |
||||||
|
val results = ArrayList<List<String>>() |
||||||
|
for (rl in rules) { |
||||||
|
val temp = getStringList(rl) |
||||||
|
if (temp.isNotEmpty()) { |
||||||
|
results.add(temp) |
||||||
|
if (temp.isNotEmpty() && elementsType == "|") { |
||||||
|
break |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
if (results.size > 0) { |
||||||
|
if ("%" == elementsType) { |
||||||
|
for (i in 0 until results[0].size) { |
||||||
|
for (temp in results) { |
||||||
|
if (i < temp.size) { |
||||||
|
result.add(temp[i]) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} else { |
||||||
|
for (temp in results) { |
||||||
|
result.addAll(temp) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return result |
||||||
|
} |
||||||
|
|
||||||
|
fun getString(rule: String): String? { |
||||||
|
val rules: Array<String> |
||||||
|
val elementsType: String |
||||||
|
if (rule.contains("&&")) { |
||||||
|
rules = rule.split("&&".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() |
||||||
|
elementsType = "&" |
||||||
|
} else { |
||||||
|
rules = rule.split("\\|\\|".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() |
||||||
|
elementsType = "|" |
||||||
|
} |
||||||
|
if (rules.size == 1) { |
||||||
|
/*Object object = jxDocument.selOne(rule); |
||||||
|
result = object instanceof Element ? ((Element) object).html() : (String) object;*/ |
||||||
|
val jxNodes = jxDocument!!.selN(rule) ?: return null |
||||||
|
return TextUtils.join(",", jxNodes) |
||||||
|
} else { |
||||||
|
val sb = StringBuilder() |
||||||
|
for (rl in rules) { |
||||||
|
val temp = getString(rl) |
||||||
|
if (!TextUtils.isEmpty(temp)) { |
||||||
|
sb.append(temp) |
||||||
|
if (elementsType == "|") { |
||||||
|
break |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return sb.toString() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -1,2 +0,0 @@ |
|||||||
package io.legado.app.model.analyzeRule |
|
||||||
|
|
Loading…
Reference in new issue