Baozimanhua: various cleanup and fixes (#11991)
This commit is contained in:
parent
e22adc0fc9
commit
d1abd5cf30
|
@ -1,3 +1,9 @@
|
|||
## 1.2.6 (2022-05-27)
|
||||
|
||||
- 整理代码
|
||||
- 切除部分罕见情况上下端都有的 banner
|
||||
- 修复部分章节较少的漫画解析章节列表为空的问题
|
||||
|
||||
## 1.2.5 (2022-05-17)
|
||||
|
||||
- 提高 banner 识别容错率,切除噪声更多的 banner
|
||||
|
|
|
@ -5,7 +5,7 @@ ext {
|
|||
extName = 'Baozimanhua'
|
||||
pkgNameSuffix = 'zh.baozimanhua'
|
||||
extClass = '.Baozimanhua'
|
||||
extVersionCode = 5
|
||||
extVersionCode = 6
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)) {
|
||||
|
|
Loading…
Reference in New Issue