feat: 多页目录同时获取

pull/95/head
kunfei 5 years ago
parent 7a01d76440
commit 25dc9e62df
  1. 197
      app/src/main/java/io/legado/app/model/webBook/BookChapterList.kt

@ -7,11 +7,14 @@ import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookChapter import io.legado.app.data.entities.BookChapter
import io.legado.app.data.entities.BookSource import io.legado.app.data.entities.BookSource
import io.legado.app.data.entities.rule.TocRule import io.legado.app.data.entities.rule.TocRule
import io.legado.app.help.coroutine.Coroutine
import io.legado.app.model.Debug import io.legado.app.model.Debug
import io.legado.app.model.analyzeRule.AnalyzeRule import io.legado.app.model.analyzeRule.AnalyzeRule
import io.legado.app.model.analyzeRule.AnalyzeUrl import io.legado.app.model.analyzeRule.AnalyzeUrl
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.withContext import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
import kotlin.coroutines.suspendCoroutine
object BookChapterList { object BookChapterList {
@ -21,95 +24,143 @@ object BookChapterList {
body: String?, body: String?,
bookSource: BookSource, bookSource: BookSource,
baseUrl: String baseUrl: String
): List<BookChapter> { ): List<BookChapter> = suspendCoroutine { block ->
var chapterList = ArrayList<BookChapter>() try {
body ?: throw Exception( val chapterList = ArrayList<BookChapter>()
App.INSTANCE.getString(R.string.error_get_web_content, baseUrl) body ?: throw Exception(
) App.INSTANCE.getString(R.string.error_get_web_content, baseUrl)
Debug.log(bookSource.bookSourceUrl, "≡获取成功:${baseUrl}") )
val tocRule = bookSource.getTocRule() Debug.log(bookSource.bookSourceUrl, "≡获取成功:${baseUrl}")
val nextUrlList = arrayListOf(baseUrl) val tocRule = bookSource.getTocRule()
var reverse = false val nextUrlList = arrayListOf(baseUrl)
var listRule = tocRule.chapterList ?: "" var reverse = false
if (listRule.startsWith("-")) { var listRule = tocRule.chapterList ?: ""
reverse = true if (listRule.startsWith("-")) {
listRule = listRule.substring(1) reverse = true
} listRule = listRule.substring(1)
if (listRule.startsWith("+")) {
listRule = listRule.substring(1)
}
var chapterData =
analyzeChapterList(body, baseUrl, tocRule, listRule, book, bookSource, log = true)
chapterData.chapterList?.let {
chapterList.addAll(it)
}
if (chapterData.nextUrl.size == 1) {
var nextUrl = chapterData.nextUrl[0]
while (nextUrl.isNotEmpty() && !nextUrlList.contains(nextUrl)) {
nextUrlList.add(nextUrl)
AnalyzeUrl(
ruleUrl = nextUrl, book = book, headerMapF = bookSource.getHeaderMap()
).getResponseAwait()
.body?.let { nextBody ->
chapterData = analyzeChapterList(
nextBody, nextUrl, tocRule, listRule,
book, bookSource, log = false
)
nextUrl = if (chapterData.nextUrl.isNotEmpty())
chapterData.nextUrl[0]
else ""
chapterData.chapterList?.let {
chapterList.addAll(it)
}
}
} }
Debug.log(bookSource.bookSourceUrl, "◇目录总页数:${nextUrlList.size}") if (listRule.startsWith("+")) {
} else if (chapterData.nextUrl.size > 1) { listRule = listRule.substring(1)
val chapterDataList = arrayListOf<ChapterData<String>>()
for (item in chapterData.nextUrl) {
val data = ChapterData(nextUrl = item)
chapterDataList.add(data)
} }
for (item in chapterDataList) { var chapterData =
withContext(coroutineScope.coroutineContext) { analyzeChapterList(body, baseUrl, tocRule, listRule, book, bookSource, log = true)
val nextBody = AnalyzeUrl( chapterData.chapterList?.let {
ruleUrl = item.nextUrl, chapterList.addAll(it)
book = book,
headerMapF = bookSource.getHeaderMap()
).getResponseAwait().body
val nextChapterData = analyzeChapterList(
nextBody, item.nextUrl, tocRule, listRule, book, bookSource
)
item.chapterList = nextChapterData.chapterList
}
} }
for (item in chapterDataList) { when (chapterData.nextUrl.size) {
item.chapterList?.let { 0 -> {
chapterList.addAll(it) block.resume(finish(book, chapterList, reverse))
}
1 -> {
Coroutine.async(scope = coroutineScope) {
var nextUrl = chapterData.nextUrl[0]
while (nextUrl.isNotEmpty() && !nextUrlList.contains(nextUrl)) {
nextUrlList.add(nextUrl)
AnalyzeUrl(
ruleUrl = nextUrl,
book = book,
headerMapF = bookSource.getHeaderMap()
).getResponseAwait()
.body?.let { nextBody ->
chapterData = analyzeChapterList(
nextBody, nextUrl, tocRule, listRule,
book, bookSource, log = false
)
nextUrl = if (chapterData.nextUrl.isNotEmpty()) {
chapterData.nextUrl[0]
} else ""
chapterData.chapterList?.let {
chapterList.addAll(it)
}
}
}
Debug.log(bookSource.bookSourceUrl, "◇目录总页数:${nextUrlList.size}")
block.resume(finish(book, chapterList, reverse))
}.onError {
block.resumeWithException(it)
}
}
else -> {
val chapterDataList = arrayListOf<ChapterData<String>>()
for (item in chapterData.nextUrl) {
val data = ChapterData(nextUrl = item)
chapterDataList.add(data)
}
for (item in chapterDataList) {
Coroutine.async(scope = coroutineScope) {
val nextBody = AnalyzeUrl(
ruleUrl = item.nextUrl,
book = book,
headerMapF = bookSource.getHeaderMap()
).getResponseAwait().body
val nextChapterData = analyzeChapterList(
nextBody, item.nextUrl, tocRule, listRule, book, bookSource
)
synchronized(chapterDataList) {
val isFinished = addChapterListIsFinish(
chapterDataList,
item,
nextChapterData.chapterList
)
if (isFinished) {
chapterDataList.forEach { item ->
item.chapterList?.let {
chapterList.addAll(it)
}
}
block.resume(finish(book, chapterList, reverse))
}
}
}.onError {
block.resumeWithException(it)
}
}
} }
} }
} catch (e: Exception) {
block.resumeWithException(e)
}
}
private fun addChapterListIsFinish(
chapterDataList: ArrayList<ChapterData<String>>,
chapterData: ChapterData<String>,
chapterList: List<BookChapter>?
): Boolean {
chapterData.chapterList = chapterList
chapterDataList.forEach {
if (it.chapterList == null) {
return false
}
} }
return true
}
private fun finish(
book: Book,
chapterList: ArrayList<BookChapter>,
reverse: Boolean
): ArrayList<BookChapter> {
//去重 //去重
if (!reverse) { if (!reverse) {
chapterList.reverse() chapterList.reverse()
} }
val lh = LinkedHashSet(chapterList) val lh = LinkedHashSet(chapterList)
chapterList = ArrayList(lh) val list = ArrayList(lh)
chapterList.reverse() list.reverse()
for ((index, item) in chapterList.withIndex()) { for ((index, item) in list.withIndex()) {
item.index = index item.index = index
} }
book.latestChapterTitle = chapterList.last().title book.latestChapterTitle = list.last().title
book.durChapterTitle = book.durChapterTitle =
chapterList.getOrNull(book.durChapterIndex)?.title ?: book.latestChapterTitle list.getOrNull(book.durChapterIndex)?.title ?: book.latestChapterTitle
if (book.totalChapterNum < chapterList.size) { if (book.totalChapterNum < list.size) {
book.lastCheckCount = chapterList.size - book.totalChapterNum book.lastCheckCount = list.size - book.totalChapterNum
} }
book.totalChapterNum = chapterList.size book.totalChapterNum = list.size
return chapterList return list
} }
private fun analyzeChapterList( private fun analyzeChapterList(
body: String?, body: String?,
baseUrl: String, baseUrl: String,

Loading…
Cancel
Save