Baozimanhua: various cleanup and fixes (#11991)

This commit is contained in:
kasperskier 2022-05-27 20:03:07 +08:00 committed by GitHub
parent e22adc0fc9
commit d1abd5cf30
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 36 additions and 42 deletions

View File

@ -1,3 +1,9 @@
## 1.2.6 (2022-05-27)
- 整理代码
- 切除部分罕见情况上下端都有的 banner
- 修复部分章节较少的漫画解析章节列表为空的问题
## 1.2.5 (2022-05-17)
- 提高 banner 识别容错率,切除噪声更多的 banner

View File

@ -5,7 +5,7 @@ ext {
extName = 'Baozimanhua'
pkgNameSuffix = 'zh.baozimanhua'
extClass = '.Baozimanhua'
extVersionCode = 5
extVersionCode = 6
}
apply from: "$rootDir/common.gradle"

View File

@ -8,6 +8,7 @@ import okhttp3.MediaType.Companion.toMediaType
import okhttp3.Response
import okhttp3.ResponseBody.Companion.toResponseBody
import java.io.ByteArrayOutputStream
import java.util.EnumSet
import kotlin.math.abs
class BannerInterceptor : Interceptor {
@ -34,17 +35,13 @@ class BannerInterceptor : Interceptor {
val contentType = body.contentType()
val content = body.bytes()
val bitmap = BitmapFactory.decodeByteArray(content, 0, content.size)
val position = checkBanner(bitmap)
return if (position == null) {
val positions = checkBanner(bitmap)
return if (positions.isEmpty()) {
response.newBuilder().body(content.toResponseBody(contentType)).build()
} else {
val result = Bitmap.createBitmap(
bitmap, 0,
when (position) {
BannerPosition.TOP -> h
BannerPosition.BOTTOM -> 0
},
bitmap.width, bitmap.height - h
bitmap, 0, if (positions.contains(BannerPosition.TOP)) h else 0,
bitmap.width, bitmap.height - h * positions.size
)
val output = ByteArrayOutputStream()
result.compress(Bitmap.CompressFormat.JPEG, 90, output)
@ -53,16 +50,17 @@ class BannerInterceptor : Interceptor {
}
}
private fun checkBanner(image: Bitmap): BannerPosition? {
if (image.width < w || image.height < h) return null
if ((image.width - w) % 2 != 0) return null
private fun checkBanner(image: Bitmap): EnumSet<BannerPosition> {
val result = EnumSet.noneOf(BannerPosition::class.java)
if (image.width < w || image.height < h) return result
if ((image.width - w) % 2 != 0) return result
val pad = (image.width - w) / 2
val buf = IntArray(size)
image.getPixels(buf, 0, w, pad, 0, w, h) // top
if (isIdentical(bannerBuffer, buf)) return BannerPosition.TOP
if (isIdentical(bannerBuffer, buf)) result.add(BannerPosition.TOP)
image.getPixels(buf, 0, w, pad, image.height - h, w, h) // bottom
if (isIdentical(bannerBuffer, buf)) return BannerPosition.BOTTOM
return null
if (isIdentical(bannerBuffer, buf)) result.add(BannerPosition.BOTTOM)
return result
}
private fun isIdentical(a: IntArray, b: IntArray): Boolean {

View File

@ -40,17 +40,18 @@ class Baozimanhua : ParsedHttpSource(), ConfigurableSource {
override val supportsLatest = true
override val client: OkHttpClient = network.cloudflareClient.newBuilder()
.addNetworkInterceptor(BannerInterceptor()).build()
.addInterceptor(BannerInterceptor()).build()
override fun chapterListSelector(): String = "div.pure-g[id^=chapter] > div"
override fun chapterListSelector() = throw UnsupportedOperationException("Not used.")
override fun chapterListParse(response: Response): List<SChapter> {
val document = response.asJsoup()
val chapters = document.select(chapterListSelector()).map { element ->
chapterFromElement(element)
}
// chapters are listed oldest to newest in the source
return chapters.reversed()
return if (document.select(".l-box > .pure-g").size == 1) { // only latest chapters
document.select(".l-box > .pure-g > div")
} else {
// chapters are listed oldest to newest in the source
document.select(".l-box > .pure-g[id^=chapter] > div").reversed()
}.map { chapterFromElement(it) }
}
override fun chapterFromElement(element: Element): SChapter {
@ -70,15 +71,12 @@ class Baozimanhua : ParsedHttpSource(), ConfigurableSource {
}
}
override fun popularMangaNextPageSelector() = throw java.lang.UnsupportedOperationException("Not used.")
override fun popularMangaNextPageSelector(): String? = null
override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/classify", headers)
override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/classify?page=$page", headers)
override fun popularMangaParse(response: Response): MangasPage {
val document = response.asJsoup()
val mangas = document.select(popularMangaSelector()).map { element ->
popularMangaFromElement(element)
}
val mangas = super.popularMangaParse(response).mangas
return MangasPage(mangas, mangas.size == 36)
}
@ -88,18 +86,10 @@ class Baozimanhua : ParsedHttpSource(), ConfigurableSource {
return popularMangaFromElement(element)
}
override fun latestUpdatesNextPageSelector() = throw java.lang.UnsupportedOperationException("Not used.")
override fun latestUpdatesNextPageSelector(): String? = null
override fun latestUpdatesRequest(page: Int): Request = GET("$baseUrl/list/new", headers)
override fun latestUpdatesParse(response: Response): MangasPage {
val document = response.asJsoup()
val mangas = document.select(popularMangaSelector()).map { element ->
popularMangaFromElement(element)
}
return MangasPage(mangas, mangas.size == 12)
}
override fun mangaDetailsParse(document: Document): SManga {
return SManga.create().apply {
title = document.select("h1.comics-detail__title").text().trim()
@ -113,23 +103,23 @@ class Baozimanhua : ParsedHttpSource(), ConfigurableSource {
"已完結" -> SManga.COMPLETED
else -> SManga.UNKNOWN
}
// TODO: upload date by selector "em" in format "(2021年06月29日 更新)"
}
}
override fun pageListParse(document: Document): List<Page> {
val pages = document.select(".comic-contain > .chapter-img > img").mapIndexed { index, element ->
return document.select(".comic-contain > .chapter-img > img").mapIndexed { index, element ->
Page(index, imageUrl = element.attr("data-src").trim() + COMIC_IMAGE_SUFFIX)
}
return pages
}
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException("Not used.")
override fun searchMangaSelector() = throw java.lang.UnsupportedOperationException("Not used.")
override fun searchMangaSelector() = throw UnsupportedOperationException("Not used.")
override fun searchMangaFromElement(element: Element) = throw java.lang.UnsupportedOperationException("Not used.")
override fun searchMangaFromElement(element: Element) = throw UnsupportedOperationException("Not used.")
override fun searchMangaNextPageSelector() = throw java.lang.UnsupportedOperationException("Not used.")
override fun searchMangaNextPageSelector() = throw UnsupportedOperationException("Not used.")
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
return if (query.startsWith(ID_SEARCH_PREFIX)) {