修复包子漫画导航解析
This commit is contained in:
parent
01fa3eade2
commit
64432f50ba
@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.extension.all.mangadex
|
||||
import android.content.SharedPreferences
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.Response
|
||||
import java.io.IOException
|
||||
|
||||
/**
|
||||
* Interceptor to set custom useragent for MangaDex
|
||||
|
@ -1,6 +1,5 @@
|
||||
package eu.kanade.tachiyomi.extension.en.collectedcurios
|
||||
|
||||
import android.util.Log
|
||||
import eu.kanade.tachiyomi.source.model.FilterList
|
||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||
import eu.kanade.tachiyomi.source.model.Page
|
||||
@ -58,7 +57,7 @@ class Collectedcurios : ParsedHttpSource() {
|
||||
description = "Spider and Scorpion webcomic."
|
||||
thumbnail_url = "https://www.collectedcurios.com/images/CC_2011_Spider_And_Scorpion_Button.jpg"
|
||||
},
|
||||
*/
|
||||
*/
|
||||
),
|
||||
false,
|
||||
),
|
||||
|
@ -68,7 +68,7 @@ class Twi4 : HttpSource() {
|
||||
author = manga.select("div.hgroup > p").text()
|
||||
status =
|
||||
if (manga.select("ul:first-child > li:last-child > em.is-completed")
|
||||
.isEmpty()
|
||||
.isEmpty()
|
||||
) {
|
||||
SManga.ONGOING
|
||||
} else {
|
||||
|
@ -97,11 +97,15 @@ class MangaClub : ParsedHttpSource() {
|
||||
title = document.select("div.info strong").text().replace("\\'", "'").substringBefore("/").trim()
|
||||
author = document.select("div.info a[href*=author]").joinToString(", ") { it.text().trim() }
|
||||
artist = author
|
||||
status = if (document.select("div.fullstory").text().contains("Данное произведение лицензировано на территории РФ. Главы удалены.")) SManga.LICENSED else when (document.select("div.info a[href*=status_translation]").text().trim()) {
|
||||
"Продолжается" -> SManga.ONGOING
|
||||
"Завершен" -> SManga.COMPLETED
|
||||
"Заморожено/Заброшено" -> SManga.ON_HIATUS
|
||||
else -> SManga.UNKNOWN
|
||||
status = if (document.select("div.fullstory").text().contains("Данное произведение лицензировано на территории РФ. Главы удалены.")) {
|
||||
SManga.LICENSED
|
||||
} else {
|
||||
when (document.select("div.info a[href*=status_translation]").text().trim()) {
|
||||
"Продолжается" -> SManga.ONGOING
|
||||
"Завершен" -> SManga.COMPLETED
|
||||
"Заморожено/Заброшено" -> SManga.ON_HIATUS
|
||||
else -> SManga.UNKNOWN
|
||||
}
|
||||
}
|
||||
|
||||
description = document.select(".description").first()!!.text()
|
||||
|
@ -108,7 +108,10 @@ class Baimangu : ConfigurableSource, ParsedHttpSource() {
|
||||
// Search
|
||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||
return if (query.isNotBlank()) {
|
||||
GET("$baseUrl/vodsearch/$query----------$page---", headers)
|
||||
// GET("$baseUrl/vodsearch/$query----------$page---", headers)
|
||||
// https://www.darpou.com/cccsearch/-------.html?wd=%E8%BD%AC%E7%94%9F%E8%B4%B5%E6%97%8F
|
||||
// https://www.darpou.com/cccsearch/------.html?wd=%E8%BD%AC%E7%94%9F%E8%B4%B5%E6%97%8F
|
||||
GET("$baseUrl/cccsearch/-------.html?wd=$query", headers)
|
||||
} else {
|
||||
var channelValue = "4" // 漫画大全
|
||||
var sortValue = "time" // 按时间
|
||||
@ -128,7 +131,8 @@ class Baimangu : ConfigurableSource, ParsedHttpSource() {
|
||||
// https://www.darpou.com/vodshow/2-----------.html
|
||||
// https://www.darpou.com/vodshow/2--hits------3---.html
|
||||
|
||||
val url = "$baseUrl/vodshow/$channelValue--$sortValue------$page---"
|
||||
// val url = "$baseUrl/vodshow/$channelValue--$sortValue------$page---"
|
||||
val url = "$baseUrl/vodshow/$channelValue--$sortValue"
|
||||
|
||||
GET(url, headers)
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ ext {
|
||||
extName = 'Baozimh.org'
|
||||
pkgNameSuffix = 'zh.baozimhorg'
|
||||
extClass = '.BaozimhOrg'
|
||||
extVersionCode = 28
|
||||
extVersionCode = 29
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
||||
|
@ -1,6 +1,7 @@
|
||||
package eu.kanade.tachiyomi.extension.zh.baozimhorg
|
||||
|
||||
import android.app.Application
|
||||
import android.util.Log
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.PreferenceScreen
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
@ -17,24 +18,28 @@ import okhttp3.HttpUrl
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.Jsoup
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import org.jsoup.select.Evaluator
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
|
||||
// Uses WPManga + GeneratePress/Blocksy Child
|
||||
class BaozimhOrg : HttpSource(), ConfigurableSource {
|
||||
|
||||
override val name get() = "包子漫画导航"
|
||||
override val name get() = "包子漫画导航 by 芋头"
|
||||
override val lang get() = "zh"
|
||||
override val supportsLatest get() = true
|
||||
|
||||
override val baseUrl: String
|
||||
private val baseHttpUrl: HttpUrl
|
||||
private val enableGenres: Boolean
|
||||
private val TAG = "包子"
|
||||
|
||||
init {
|
||||
val mirrors = MIRRORS
|
||||
@ -50,24 +55,28 @@ class BaozimhOrg : HttpSource(), ConfigurableSource {
|
||||
.build()
|
||||
|
||||
private fun getKey(link: String): String {
|
||||
val pathSegments = baseHttpUrl.resolve(link)!!.pathSegments
|
||||
val fromIndex = if (pathSegments[0] == "manga") 1 else 0
|
||||
val toIndex = if (pathSegments.last().isEmpty()) pathSegments.size - 1 else pathSegments.size
|
||||
val list = pathSegments.subList(fromIndex, toIndex).toMutableList()
|
||||
list[0] = list[0].split("-").take(2).joinToString("-")
|
||||
return list.joinToString("/")
|
||||
/* val pathSegments = baseHttpUrl.resolve(link)!!.pathSegments
|
||||
val fromIndex = if (pathSegments[0] == "manga") 1 else 0
|
||||
val toIndex =
|
||||
if (pathSegments.last().isEmpty()) pathSegments.size - 1 else pathSegments.size
|
||||
val list = pathSegments.subList(fromIndex, toIndex).toMutableList()
|
||||
list[0] = list[0].split("-").take(2).joinToString("-")
|
||||
return list.joinToString("/")*/
|
||||
return link.split("manga/")[1]
|
||||
}
|
||||
|
||||
override fun popularMangaRequest(page: Int) = GET("$baseUrl/hots/page/$page/", headers)
|
||||
|
||||
override fun popularMangaParse(response: Response): MangasPage {
|
||||
val document = response.asJsoup().also(::parseGenres)
|
||||
val mangas = document.select("article.wp-manga").map { element ->
|
||||
Log.i(TAG, "popularMangaParse: 3")
|
||||
val mangas = document.select(".cardlist a").map { element ->
|
||||
SManga.create().apply {
|
||||
val link = element.selectFirst(Evaluator.Tag("h2"))!!.child(0)
|
||||
url = getKey(link.attr("href"))
|
||||
title = link.ownText()
|
||||
thumbnail_url = element.selectFirst(Evaluator.Tag("img"))!!.imgSrc
|
||||
// val link = element.selectFirst(Evaluator.Tag("h3"))!!.child(0)
|
||||
url = element.attr("href").split("/manga/")[1]
|
||||
Log.i("包子", "热门链接:$url ")
|
||||
title = element.select("h3").text()
|
||||
thumbnail_url = element.select("img").attr("src")
|
||||
}
|
||||
}
|
||||
val hasNextPage = document.selectFirst(Evaluator.Class("next"))?.tagName() == "a" ||
|
||||
@ -81,12 +90,18 @@ class BaozimhOrg : HttpSource(), ConfigurableSource {
|
||||
|
||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||
if (query.isNotEmpty()) {
|
||||
val url = "$baseUrl/page/$page/".toHttpUrl().newBuilder()
|
||||
.addQueryParameter("s", query)
|
||||
val url = "$baseUrl/s/$query".toHttpUrl().newBuilder()
|
||||
.addQueryParameter("page", page.toString())
|
||||
Log.i("包子", "搜索链接:$url ")
|
||||
return Request.Builder().url(url.build()).headers(headers).build()
|
||||
}
|
||||
for (filter in filters) {
|
||||
if (filter is UriPartFilter) return GET(baseUrl + filter.toUriPart() + "page/$page/", headers)
|
||||
if (filter is UriPartFilter) {
|
||||
return GET(
|
||||
baseUrl + filter.toUriPart() + "page/$page/",
|
||||
headers,
|
||||
)
|
||||
}
|
||||
}
|
||||
return popularMangaRequest(page)
|
||||
}
|
||||
@ -101,36 +116,52 @@ class BaozimhOrg : HttpSource(), ConfigurableSource {
|
||||
|
||||
override fun mangaDetailsParse(response: Response) = SManga.create().apply {
|
||||
val document = response.asJsoup()
|
||||
title = document.selectFirst(Evaluator.Tag("h1"))!!.ownText()
|
||||
author = document.selectFirst(Evaluator.Class("author-content"))!!.children().joinToString { it.ownText() }
|
||||
description = document.selectFirst(".descrip_manga_info, .wp-block-stackable-text")!!.text()
|
||||
thumbnail_url = document.selectFirst("img.wp-post-image")!!.imgSrc
|
||||
Log.i(TAG, "mangaDetailsParse: " + response.request.url)
|
||||
title = document.select("#info").select("h1")[0].childNode(0).toString()
|
||||
author = document.select(".text-small").select(".py-1")
|
||||
.select(".pb-2")[0].select("span")[1].text()
|
||||
description = document.select("#info").select("p")[0].childNode(0).toString()
|
||||
thumbnail_url = document.select("#MangaCard").select("img").attr("src")
|
||||
|
||||
val genreList = document.selectFirst(Evaluator.Class("genres-content"))!!
|
||||
.children().eachText().toMutableSet()
|
||||
if ("连载中" in genreList) {
|
||||
genreList.remove("连载中")
|
||||
val _status = document.select("#info").select("h1")[0].childNode(1).childNode(0).toString()
|
||||
Log.i(TAG, "mangaDetailsParse: $_status")
|
||||
if ("連載中" in _status) {
|
||||
status = SManga.ONGOING
|
||||
} else if ("已完结" in genreList) {
|
||||
genreList.remove("已完结")
|
||||
} else {
|
||||
status = SManga.COMPLETED
|
||||
}
|
||||
genre = genreList.joinToString()
|
||||
}
|
||||
|
||||
override fun chapterListRequest(manga: SManga): Request {
|
||||
val url = manga.url
|
||||
Log.i(
|
||||
TAG,
|
||||
"${manga.title} | ${manga.author} | ${manga.genre} | ${manga.description} | ${manga.artist} | ${manga.update_strategy}",
|
||||
)
|
||||
if (url[0] == '/') throw Exception(MIGRATE)
|
||||
return GET("$baseUrl/chapterlist/$url/", headers)
|
||||
}
|
||||
|
||||
override fun chapterListParse(response: Response): List<SChapter> {
|
||||
val document = response.asJsoup()
|
||||
return document.selectFirst(Evaluator.Class("version-chaps"))!!.children().map {
|
||||
var document = response.asJsoup()
|
||||
val allchapters = document.getElementById("allchapters")
|
||||
val host = allchapters?.attr("data-host")
|
||||
val mid = allchapters?.attr("data-mid")
|
||||
|
||||
document = Jsoup.connect("$host/manga/get?mid=$mid&mode=all").get()
|
||||
Log.i(TAG, "章节html ${document.text()}")
|
||||
Log.i(TAG, "chapterListParse: $host | $mid | ${document.select("a").size}")
|
||||
return document.select("a").map {
|
||||
SChapter.create().apply {
|
||||
url = getKey(it.attr("href"))
|
||||
name = it.ownText()
|
||||
date_upload = parseChapterDate(it.child(0).text())
|
||||
name = it.attr("data-ct")
|
||||
date_upload = parseChapterDate(it.select("span")[1].text())
|
||||
Log.i(
|
||||
TAG,
|
||||
"chapterListParse: 时间 $date_upload | ${
|
||||
it.selectFirst("a")!!.select("span")[1].text()
|
||||
} | key url = $url | srcUrl = ${it.attr("href")}",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -142,10 +173,16 @@ class BaozimhOrg : HttpSource(), ConfigurableSource {
|
||||
}
|
||||
|
||||
override fun pageListParse(response: Response): List<Page> {
|
||||
val document = response.asJsoup()
|
||||
var document = response.asJsoup()
|
||||
// Jsoup won't ignore duplicates inside <noscript> tag
|
||||
document.select(Evaluator.Tag("noscript")).remove()
|
||||
return document.select("img[decoding=async]").mapIndexed { index, element ->
|
||||
Log.i(TAG, "pageListParse: 解析漫画地址:${document.baseUri()}")
|
||||
val chapterContent = document.getElementById("chapterContent")
|
||||
val host = chapterContent?.attr("data-host")
|
||||
val mid = chapterContent?.attr("data-ms")
|
||||
val cs = chapterContent?.attr("data-cs")
|
||||
document = Jsoup.connect("$host/chapter/getcontent?m=$mid&c=$cs").get()
|
||||
return document.select("img[data-sizes=auto]").mapIndexed { index, element ->
|
||||
Log.i(TAG, "pageListParse: 漫画地址 ${element.imgSrc}")
|
||||
Page(index, imageUrl = element.imgSrc)
|
||||
}
|
||||
}
|
||||
@ -156,14 +193,31 @@ class BaozimhOrg : HttpSource(), ConfigurableSource {
|
||||
|
||||
private fun parseGenres(document: Document) {
|
||||
if (!enableGenres || genres.isNotEmpty()) return
|
||||
val box = document.selectFirst(Evaluator.Class("wp-block-navigation__container")) ?: return
|
||||
/*val box = document.selectFirst(Evaluator.Class("container")) ?: return
|
||||
Log.i(TAG, "container size ${box.childrenSize()}")
|
||||
val items = box.children()
|
||||
genres = buildList(items.size + 1) {
|
||||
add(Pair("全部", "/allmanga/"))
|
||||
add(Pair("全部", "/manga/"))
|
||||
items.mapTo(this) {
|
||||
val link = it.child(0)
|
||||
Pair(link.text(), link.attr("href"))
|
||||
}
|
||||
}.toTypedArray()*/
|
||||
val items = document.select("#info").select(".py-1").select(".bg-default-200")
|
||||
Log.i(
|
||||
TAG,
|
||||
"parseGenres: info = ${document.select("#info").size} | ${
|
||||
document.select("#info").select(".py-1").size
|
||||
} | ${items.size} ",
|
||||
)
|
||||
genres = buildList(items.size) {
|
||||
add(Pair("全部", "/manga/"))
|
||||
Log.i(TAG, "parseGenres: 分类数量 ${items.size}")
|
||||
items.mapTo(this) {
|
||||
val link = it.parent()!!.attr("href")
|
||||
Log.i(TAG, "分类 ${it.text()} | $link")
|
||||
Pair(it.text(), link)
|
||||
}
|
||||
}.toTypedArray()
|
||||
}
|
||||
|
||||
@ -208,9 +262,52 @@ class BaozimhOrg : HttpSource(), ConfigurableSource {
|
||||
private val dateFormat by lazy { SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH) }
|
||||
|
||||
fun parseChapterDate(text: String): Long = try {
|
||||
dateFormat.parse(text)!!.time
|
||||
if (text.contains("天前")) {
|
||||
convertDaysAgoToTimestamp(text.trim().replace("天前", "").toInt())
|
||||
} else if (text.contains("小时前")) {
|
||||
convertHourToTimestamp(text.trim().replace("小时前", "").toInt())
|
||||
} else {
|
||||
// dateFormat.parse(text)!!.time
|
||||
convertDefTimerToTimestamp(text)
|
||||
}
|
||||
} catch (_: Throwable) {
|
||||
0
|
||||
}
|
||||
|
||||
private fun convertDaysAgoToTimestamp(daysAgo: Int): Long {
|
||||
val now = Calendar.getInstance()
|
||||
now.time = Date()
|
||||
now.add(Calendar.DATE, -daysAgo)
|
||||
return now.time.time
|
||||
}
|
||||
|
||||
private fun convertHourToTimestamp(hour: Int): Long {
|
||||
val now = Calendar.getInstance()
|
||||
now.time = Date()
|
||||
now.add(Calendar.HOUR, -hour)
|
||||
return now.time.time
|
||||
}
|
||||
|
||||
private fun convertDefTimerToTimestamp(dateString: String): Long {
|
||||
val dateFormat = SimpleDateFormat("MMM dd", Locale.ENGLISH)
|
||||
dateFormat.isLenient = false
|
||||
try {
|
||||
val date = dateFormat.parse(dateString)
|
||||
|
||||
// 由于没有提供年份,我们设置默认年份
|
||||
val calendar = Calendar.getInstance()
|
||||
calendar.setTime(date!!)
|
||||
calendar.set(
|
||||
Calendar.YEAR,
|
||||
Calendar.getInstance().get(Calendar.YEAR),
|
||||
) // 设置默认年份,比如2023
|
||||
|
||||
// 转换为时间戳
|
||||
return calendar.getTimeInMillis()
|
||||
} catch (e: Exception) {
|
||||
Log.e("包子", "convertDefTimerToTimestamp: ", e)
|
||||
return 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package eu.kanade.tachiyomi.extension.zh.baozimhorg
|
||||
|
||||
import android.util.Log
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.Response
|
||||
|
||||
@ -16,10 +17,12 @@ object UrlInterceptor : Interceptor {
|
||||
}
|
||||
|
||||
val mangaUrl = "/manga/$slug/"
|
||||
Log.i("包子", "mangaUrl = $mangaUrl url = $url")
|
||||
val headRequest = request.newBuilder()
|
||||
.head()
|
||||
.url(url.resolve(mangaUrl)!!)
|
||||
.build()
|
||||
Log.i("包子", "不知道是哪的链接:${headRequest.url} ")
|
||||
// might redirect multiple times
|
||||
val headResponse = chain.proceed(headRequest)
|
||||
if (headResponse.priorResponse == null) return chain.proceed(request)
|
||||
|
@ -30,7 +30,6 @@ import org.json.JSONObject
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.net.URLEncoder
|
||||
import java.nio.charset.Charset
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
|
Loading…
Reference in New Issue
Block a user