Merge pull request #1128 from bushixuanqi/master

修正
pull/1132/head
kunfei 3 years ago committed by GitHub
commit 7e71811aab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 12
      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. 17
      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. 82
      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
@ -61,12 +62,11 @@ data class BookChapter(
return false return false
} }
fun getAbsoluteURL(): String { fun getAbsoluteURL():String{
val urlBefore = url.substringBefore(',') val urlMatcher = AnalyzeUrl.paramPattern.matcher(url)
val urlAbsoluteBefore = NetworkUtils.getAbsoluteURL(baseUrl, urlBefore) val urlBefore = if(urlMatcher.find())url.substring(0,urlMatcher.start()) else url
return if (urlBefore.length == url.length) urlAbsoluteBefore else urlAbsoluteBefore + url.substring( val urlAbsoluteBefore = NetworkUtils.getAbsoluteURL(baseUrl,urlBefore)
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")) {
@ -141,17 +143,14 @@ class AnalyzeUrl(
* 处理URL * 处理URL
*/ */
private fun initUrl() { //replaceKeyPageJs已经替换掉额外内容,此处url是基础形式,可以直接切首个‘,’之前字符串。 private fun initUrl() { //replaceKeyPageJs已经替换掉额外内容,此处url是基础形式,可以直接切首个‘,’之前字符串。
val urlMatcher = paramPattern.matcher(ruleUrl)
urlHasQuery = ruleUrl.substringBefore(',') 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(urlMatcher.end()))?.let { option ->
GSON.fromJsonObject<UrlOption>(
ruleUrl.substring(urlHasQuery.length + 1).trim { it < '!' })?.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,43 +27,66 @@ 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( var hasMatch = true //普通图片标签是否还未处理过
"<img[^>]*data-[^=]*= *\"([^\"])\"[^>]*>", var hasMatchX = false //是否存在带参数或带数据属性的图片标签
"<img[^>]*src *= *\"([^\"{]+(?:\\{(?:[^{}]|\\{[^{}]*\\})*\\})?)\"[^>]*>" 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", if (hasMatch) { //格式化不带参数和数据属性的普通图片标签
"\n  " var appendPos0 = 0
) //缩进图片之间的非空白段落 val matcher0 = Pattern.compile("<img[^>]*src *= *\"([^\"]+)\"[^>]*>", Pattern.CASE_INSENSITIVE).matcher(strBefore) //格式化普通图片标签
) while (matcher0.find()) {
val strBefore0 = strBefore.substring(appendPos0, matcher.start())
sb.append( if (strBefore0.isBlank()) strBefore0 else strBefore0.replace("\n","\n  "))
sb.append("<img src=\"${NetworkUtils.getAbsoluteURL(redirectUrl,matcher.group(1)!!)}\">")
appendPos0 = matcher.end()
}
strBefore = if (appendPos0 < strBefore.length) strBefore.substring(appendPos0, strBefore.length) else ""
}
sb.append( sb.append(
"<img src=\"${ if (strBefore.isBlank()) strBefore else strBefore.replace("\n","\n  ") //缩进图片之间的非空白段落
NetworkUtils.getAbsoluteURL(
redirectUrl,
urlBefore
) + url.substring(urlBefore.length)
}\">"
) )
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() appendPos = matcher.end()
} } while (matcher.find())
if (appendPos != 0) endPos = appendPos hasMatch = false //普通图片标签已经处理过
} }
if (endPos < keepImgHtml.length) { if (appendPos != 0) {
sb.append( hasMatchX = true //存在带参数或带数据属性的图片标签
keepImgHtml.substring(endPos, keepImgHtml.length).replace("\n", "\n  ") 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