pull/1127/head
bushixuanqi 3 years ago
parent f0e5fa94c0
commit ef24a4d036
  1. 6
      app/src/main/java/io/legado/app/data/entities/BookChapter.kt
  2. 3
      app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt
  3. 10
      app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt
  4. 2
      app/src/main/java/io/legado/app/ui/book/read/page/provider/ChapterProvider.kt
  5. 84
      app/src/main/java/io/legado/app/utils/HtmlFormatter.kt

@ -5,6 +5,7 @@ import androidx.room.Entity
import androidx.room.ForeignKey import androidx.room.ForeignKey
import androidx.room.Ignore import androidx.room.Ignore
import androidx.room.Index import androidx.room.Index
import io.legado.app.model.analyzeRule.AnalyzeUrl
import io.legado.app.utils.GSON import io.legado.app.utils.GSON
import io.legado.app.utils.MD5Utils import io.legado.app.utils.MD5Utils
import io.legado.app.utils.NetworkUtils import io.legado.app.utils.NetworkUtils
@ -62,9 +63,10 @@ data class BookChapter(
} }
fun getAbsoluteURL():String{ fun getAbsoluteURL():String{
val urlBefore = url.substringBefore(',') val urlMatcher = AnalyzeUrl.paramPattern.matcher(url)
val urlBefore = if(urlMatcher.find())url.substring(0,urlMatcher.start()) else url
val urlAbsoluteBefore = NetworkUtils.getAbsoluteURL(baseUrl,urlBefore) val urlAbsoluteBefore = NetworkUtils.getAbsoluteURL(baseUrl,urlBefore)
return if(urlBefore.length == url.length) urlAbsoluteBefore else urlAbsoluteBefore + url.substring(urlBefore.length) return if(urlBefore.length == url.length) urlAbsoluteBefore else urlAbsoluteBefore + url.substring(urlMatcher.end())
} }
fun getFileName(): String = String.format("%05d-%s.nb", index, MD5Utils.md5Encode16(title)) fun getFileName(): String = String.format("%05d-%s.nb", index, MD5Utils.md5Encode16(title))

@ -65,7 +65,8 @@ class AnalyzeRule(val ruleData: RuleDataInterface) : JsExtensions {
fun setRedirectUrl(url: String): URL? { fun setRedirectUrl(url: String): URL? {
kotlin.runCatching { kotlin.runCatching {
redirectUrl = URL(url.substringBefore(',')) val urlMatcher = AnalyzeUrl.paramPattern.matcher(url)
redirectUrl = URL( if(urlMatcher.find())url.substring(0,urlMatcher.start()) else url)
} }
return redirectUrl return redirectUrl
} }

@ -39,6 +39,7 @@ class AnalyzeUrl(
headerMapF: Map<String, String>? = null headerMapF: Map<String, String>? = null
) : JsExtensions { ) : JsExtensions {
companion object { companion object {
val paramPattern = Pattern.compile("\\s*,\\s*(?=\\{)")
private val pagePattern = Pattern.compile("<(.*?)>") private val pagePattern = Pattern.compile("<(.*?)>")
} }
@ -55,7 +56,8 @@ class AnalyzeUrl(
private var retry: Int = 0 private var retry: Int = 0
init { init {
baseUrl = baseUrl.substringBefore(',') val urlMatcher = paramPattern.matcher(baseUrl)
if(urlMatcher.find())baseUrl = baseUrl.substring(0,urlMatcher.start())
headerMapF?.let { headerMapF?.let {
headerMap.putAll(it) headerMap.putAll(it)
if (it.containsKey("proxy")) { if (it.containsKey("proxy")) {
@ -142,14 +144,14 @@ class AnalyzeUrl(
*/ */
private fun initUrl() { //replaceKeyPageJs已经替换掉额外内容,此处url是基础形式,可以直接切首个‘,’之前字符串。 private fun initUrl() { //replaceKeyPageJs已经替换掉额外内容,此处url是基础形式,可以直接切首个‘,’之前字符串。
urlHasQuery = ruleUrl.substringBefore(',') val urlMatcher = paramPattern.matcher(ruleUrl)
urlHasQuery = if(urlMatcher.find())ruleUrl.substring(0,urlMatcher.start()) else ruleUrl
url = NetworkUtils.getAbsoluteURL(baseUrl,urlHasQuery ) url = NetworkUtils.getAbsoluteURL(baseUrl,urlHasQuery )
NetworkUtils.getBaseUrl(url)?.let { NetworkUtils.getBaseUrl(url)?.let {
baseUrl = it baseUrl = it
} }
if(urlHasQuery.length != ruleUrl.length ) { if(urlHasQuery.length != ruleUrl.length ) {
GSON.fromJsonObject<UrlOption>(ruleUrl.substring(urlHasQuery.length + 1).trim{ it < '!'})?.let { option -> GSON.fromJsonObject<UrlOption>(ruleUrl.substring(urlMatcher.end()))?.let { option ->
option.method?.let { option.method?.let {
if (it.equals("POST", true)) method = RequestMethod.POST if (it.equals("POST", true)) method = RequestMethod.POST

@ -146,7 +146,7 @@ object ChapterProvider {
return TextChapter( return TextChapter(
bookChapter.index, bookChapter.title, bookChapter.index, bookChapter.title,
bookChapter.getAbsoluteURL().substringBefore(','), bookChapter.getAbsoluteURL().substringBefore(",{"), //getAbsoluteURL已经格式过
textPages, chapterSize textPages, chapterSize
) )
} }

@ -1,5 +1,6 @@
package io.legado.app.utils package io.legado.app.utils
import io.legado.app.model.analyzeRule.AnalyzeUrl
import java.net.URL import java.net.URL
import java.util.regex.Pattern import java.util.regex.Pattern
@ -26,35 +27,68 @@ object HtmlFormatter {
.replace("[\\n\\s]+\$|^[\\n\\s]+".toRegex(), "") .replace("[\\n\\s]+\$|^[\\n\\s]+".toRegex(), "")
.replace("\\s*\\n+\\s*".toRegex(), "\n") .replace("\\s*\\n+\\s*".toRegex(), "\n")
val sb = StringBuffer() var str = ""
var endPos = 0 var endPos = 0
for(pattern in listOf("<img[^>]*src *= *\"([^\"{]+(?:\\{(?:[^{}]|\\{[^{}]*\\})*\\})?)\"[^>]*>","<img[^>]*data-[^=]*= *\"([^\"])\"[^>]*>")){ var hasMatch = true //普通图片标签是否还未处理过
var hasMatchX = false //是否存在带参数或带数据属性的图片标签
var pos = -1
val list = listOf("<img[^>]*src *= *\"([^\"{]+\\{(?:[^{}]|\\{[^}]+})+})\"[^>]*>","<img[^>]*data-[^=]*= *\"([^\"]+)\"[^>]*>","<img[^>]*src *= *\"([^\"]+)\"[^>]*>") //优先匹配用户处理过所以带参数的图片标签,其次匹配带数据属性的图片标签
while(++pos<3){
if(pos == 2) {
if(hasMatchX)break //普通图片标签只在不存在存在带参数或带数据属性的图片标签的时候匹配
else hasMatch = false //匹配带参数或带数据属性的图片标签同时也会格式化普通图片标签
}
var appendPos = 0 var appendPos = 0
val matcher = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE).matcher(keepImgHtml) val matcher =
while (matcher.find()) { Pattern.compile(list[pos], Pattern.CASE_INSENSITIVE).matcher(keepImgHtml)
val url = matcher.group(1)!! val sb = StringBuffer()
val urlBefore = url.substringBefore(',') if (matcher.find()) {
val strBefore = keepImgHtml.substring(appendPos, matcher.start()) do {
sb.append( var strBefore = keepImgHtml.substring(appendPos, matcher.start())
if(strBefore.isBlank()) strBefore else strBefore.replace("\n", "\n  ") //缩进图片之间的非空白段落
) if (hasMatch) { //格式化不带参数和数据属性的普通图片标签
sb.append( var appendPos0 = 0
"<img src=\"${ val matcher0 = Pattern.compile("<img[^>]*src *= *\"([^\"]+)\"[^>]*>", Pattern.CASE_INSENSITIVE).matcher(strBefore) //格式化普通图片标签
NetworkUtils.getAbsoluteURL( while (matcher0.find()) {
redirectUrl, val strBefore0 = strBefore.substring(appendPos, matcher.start())
urlBefore sb.append( if (strBefore0.isBlank()) strBefore0 else strBefore0.replace("\n","\n  "))
) + url.substring(urlBefore.length) sb.append("<img src=\"${NetworkUtils.getAbsoluteURL(redirectUrl,matcher.group(1)!!)}\">")
}\">" appendPos0 = matcher.end()
) }
appendPos = matcher.end() strBefore = if (appendPos0 < strBefore.length) {
strBefore.substring(appendPos0, strBefore.length).replace("\n", "\n  ") //缩进图片之后的非空白段落
} else ""
}
sb.append(
if (strBefore.isBlank()) strBefore else strBefore.replace("\n","\n  ") //缩进图片之间的非空白段落
)
if (pos == 0) {
val url = matcher.group(1)!!
val urlMatcher = AnalyzeUrl.paramPattern.matcher(url)
val find = urlMatcher.find()
sb.append("<img src=\"${
if(find) NetworkUtils.getAbsoluteURL(redirectUrl,url.substring(0,urlMatcher.start())) + url.substring(urlMatcher.end())
else url
}\">")
} else sb.append("<img src=\"${NetworkUtils.getAbsoluteURL(redirectUrl,matcher.group(1)!!)}\">")
appendPos = matcher.end()
} while (matcher.find())
hasMatch = false //普通图片标签已经处理过
} }
if(appendPos != 0)endPos = appendPos
}
if (endPos < keepImgHtml.length) { if (appendPos != 0) {
sb.append( keepImgHtml.substring( endPos, keepImgHtml.length ).replace("\n","\n  ") ) //缩进图片之后的非空白段落 hasMatchX = true //存在带参数或带数据属性的图片标签
endPos = appendPos //存在匹配,更新位置
str = sb.toString() //存在匹配,更新字符串
}
} }
return sb.toString()
}
return if (endPos < keepImgHtml.length) {
str + keepImgHtml.substring( endPos, keepImgHtml.length ).replace("\n","\n  ") //缩进图片之后的非空白段落
}else str
}
} }

Loading…
Cancel
Save