|
@@ -3,62 +3,34 @@ package io.legado.app.model.analyzeRule
|
|
|
import android.text.TextUtils
|
|
import android.text.TextUtils
|
|
|
import androidx.annotation.Keep
|
|
import androidx.annotation.Keep
|
|
|
import org.jsoup.Jsoup
|
|
import org.jsoup.Jsoup
|
|
|
-import org.jsoup.nodes.Document
|
|
|
|
|
import org.jsoup.nodes.Element
|
|
import org.jsoup.nodes.Element
|
|
|
-import org.jsoup.parser.Parser
|
|
|
|
|
|
|
+import org.jsoup.nodes.TextNode
|
|
|
import org.jsoup.select.Elements
|
|
import org.jsoup.select.Elements
|
|
|
-import org.seimicrawler.xpath.JXDocument
|
|
|
|
|
-import org.seimicrawler.xpath.JXNode
|
|
|
|
|
|
|
|
|
|
@Keep
|
|
@Keep
|
|
|
class AnalyzeByXPath(doc: Any) {
|
|
class AnalyzeByXPath(doc: Any) {
|
|
|
- private var jxNode: Any = parse(doc)
|
|
|
|
|
|
|
|
|
|
- private fun parse(doc: Any): Any {
|
|
|
|
|
- return when (doc) {
|
|
|
|
|
- is JXNode -> if (doc.isElement) doc else strToJXDocument(doc.toString())
|
|
|
|
|
- is Document -> JXDocument.create(doc)
|
|
|
|
|
- is Element -> JXDocument.create(Elements(doc))
|
|
|
|
|
- is Elements -> JXDocument.create(doc)
|
|
|
|
|
- else -> strToJXDocument(doc.toString())
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ private var element: Element = parse(doc)
|
|
|
|
|
|
|
|
- private fun strToJXDocument(html: String): JXDocument {
|
|
|
|
|
- var html1 = html
|
|
|
|
|
- if (html1.endsWith("</td>")) {
|
|
|
|
|
- html1 = "<tr>${html1}</tr>"
|
|
|
|
|
- }
|
|
|
|
|
- if (html1.endsWith("</tr>") || html1.endsWith("</tbody>")) {
|
|
|
|
|
- html1 = "<table>${html1}</table>"
|
|
|
|
|
- }
|
|
|
|
|
- if (html1.trim().startsWith("<?xml", true)) {
|
|
|
|
|
- return JXDocument.create(Jsoup.parse(html1, Parser.xmlParser()))
|
|
|
|
|
- }
|
|
|
|
|
- return JXDocument.create(html1)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private fun getResult(xPath: String): List<JXNode>? {
|
|
|
|
|
- val node = jxNode
|
|
|
|
|
- return if (node is JXNode) {
|
|
|
|
|
- node.sel(xPath)
|
|
|
|
|
- } else {
|
|
|
|
|
- (node as JXDocument).selN(xPath)
|
|
|
|
|
|
|
+ private fun parse(doc: Any): Element {
|
|
|
|
|
+ return when (doc) {
|
|
|
|
|
+ is Element -> doc
|
|
|
|
|
+ else -> Jsoup.parse(doc.toString())
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- internal fun getElements(xPath: String): List<JXNode>? {
|
|
|
|
|
|
|
+ internal fun getElements(xPath: String): Elements? {
|
|
|
|
|
|
|
|
if (xPath.isEmpty()) return null
|
|
if (xPath.isEmpty()) return null
|
|
|
|
|
|
|
|
- val jxNodes = ArrayList<JXNode>()
|
|
|
|
|
|
|
+ val jxNodes = Elements()
|
|
|
val ruleAnalyzes = RuleAnalyzer(xPath)
|
|
val ruleAnalyzes = RuleAnalyzer(xPath)
|
|
|
val rules = ruleAnalyzes.splitRule("&&", "||", "%%")
|
|
val rules = ruleAnalyzes.splitRule("&&", "||", "%%")
|
|
|
|
|
|
|
|
if (rules.size == 1) {
|
|
if (rules.size == 1) {
|
|
|
- return getResult(rules[0])
|
|
|
|
|
|
|
+ return element.selectXpath(rules[0])
|
|
|
} else {
|
|
} else {
|
|
|
- val results = ArrayList<List<JXNode>>()
|
|
|
|
|
|
|
+ val results = ArrayList<Elements>()
|
|
|
for (rl in rules) {
|
|
for (rl in rules) {
|
|
|
val temp = getElements(rl)
|
|
val temp = getElements(rl)
|
|
|
if (temp != null && temp.isNotEmpty()) {
|
|
if (temp != null && temp.isNotEmpty()) {
|
|
@@ -94,8 +66,8 @@ class AnalyzeByXPath(doc: Any) {
|
|
|
val rules = ruleAnalyzes.splitRule("&&", "||", "%%")
|
|
val rules = ruleAnalyzes.splitRule("&&", "||", "%%")
|
|
|
|
|
|
|
|
if (rules.size == 1) {
|
|
if (rules.size == 1) {
|
|
|
- getResult(xPath)?.map {
|
|
|
|
|
- result.add(it.asString())
|
|
|
|
|
|
|
+ element.selectXpath(xPath).forEach {
|
|
|
|
|
+ result.add(it.toString())
|
|
|
}
|
|
}
|
|
|
return result
|
|
return result
|
|
|
} else {
|
|
} else {
|
|
@@ -132,10 +104,22 @@ class AnalyzeByXPath(doc: Any) {
|
|
|
val ruleAnalyzes = RuleAnalyzer(rule)
|
|
val ruleAnalyzes = RuleAnalyzer(rule)
|
|
|
val rules = ruleAnalyzes.splitRule("&&", "||")
|
|
val rules = ruleAnalyzes.splitRule("&&", "||")
|
|
|
if (rules.size == 1) {
|
|
if (rules.size == 1) {
|
|
|
- getResult(rule)?.let {
|
|
|
|
|
- return TextUtils.join("\n", it)
|
|
|
|
|
|
|
+ val xpath = when {
|
|
|
|
|
+ rule.startsWith("///") -> ".${rule.substring(1)}"
|
|
|
|
|
+ rule.startsWith("/") -> ".$rule"
|
|
|
|
|
+ else -> rule
|
|
|
|
|
+ }
|
|
|
|
|
+ val x = xpath.substringAfterLast("/")
|
|
|
|
|
+ return if (x.startsWith("@")) {
|
|
|
|
|
+ element.selectXpath(xpath.substringBeforeLast("/"))
|
|
|
|
|
+ .eachAttr(x.substring(1)).let {
|
|
|
|
|
+ TextUtils.join("\n", it)
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ element.selectXpath(xpath, TextNode::class.java).let {
|
|
|
|
|
+ TextUtils.join("\n", it)
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
- return null
|
|
|
|
|
} else {
|
|
} else {
|
|
|
val textList = arrayListOf<String>()
|
|
val textList = arrayListOf<String>()
|
|
|
for (rl in rules) {
|
|
for (rl in rules) {
|