diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/grouple/GroupleParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/grouple/GroupleParser.kt index 910a8078..bf4cfa70 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/grouple/GroupleParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/grouple/GroupleParser.kt @@ -175,9 +175,9 @@ internal abstract class GroupleParser( }, author = root.selectFirst("a.person-link")?.text() ?: manga.author, isNsfw = manga.isNsfw || root.select(".alert-warning").any { it.ownText().contains(NSFW_ALERT) }, - chapters = root.selectFirst("div.chapters-link")?.selectFirst("table") - ?.select("tr:has(td > a)")?.mapChapters(reversed = true) { i, tr -> - val a = tr.selectFirst("a.chapter-link") ?: return@mapChapters null + chapters = root.requireElementById("chapters-list").select("a.chapter-link") + .mapChapters(reversed = true) { i, a -> + val tr = a.selectFirstParent("tr") ?: return@mapChapters null val href = a.attrAsRelativeUrl("href") var translators = "" val translatorElement = a.attr("title") @@ -188,7 +188,7 @@ internal abstract class GroupleParser( } MangaChapter( id = generateUid(href), - name = tr.selectFirst("a")?.text().orEmpty().removePrefix(manga.title).trim(), + name = a.text().removePrefix(manga.title).trim(), number = i + 1, url = href, uploadDate = dateFormat.tryParse(tr.selectFirst("td.date")?.text()), diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/MangaRead.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/MangaRead.kt index d376dfaf..c69709fa 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/MangaRead.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/MangaRead.kt @@ -4,6 +4,7 @@ import androidx.collection.arraySetOf import org.jsoup.nodes.Element import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser +import org.koitharu.kotatsu.parsers.exception.ParseException import org.koitharu.kotatsu.parsers.model.* import org.koitharu.kotatsu.parsers.util.* import java.util.* @@ -60,7 +61,12 @@ internal class MangaRead(context: MangaLoaderContext) : }, ) } - val root = webClient.httpGet(url.build()).parseHtml().body().selectFirstOrThrow(".search-wrap") + val body = webClient.httpGet(url.build()).parseHtml().body() + val root = body.selectFirst(".search-wrap") ?: if (body.selectFirst(".not-found-content") != null) { + return emptyList() + } else { + throw ParseException(".search-wrap not found", body.baseUri()) + } return root.select(".c-tabs-item__content").map { div -> val a = div.selectFirstOrThrow("a") val img = div.selectLastOrThrow("img") diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/util/Jsoup.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/util/Jsoup.kt index 24d1a6bd..d6917891 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/util/Jsoup.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/util/Jsoup.kt @@ -5,6 +5,7 @@ package org.koitharu.kotatsu.parsers.util import okhttp3.HttpUrl.Companion.toHttpUrlOrNull import org.jsoup.nodes.Element import org.jsoup.select.Elements +import org.jsoup.select.QueryParser import org.jsoup.select.Selector import org.koitharu.kotatsu.parsers.exception.ParseException @@ -119,3 +120,12 @@ fun Element.selectLastOrThrow(cssQuery: String): Element { fun Element.textOrNull(): String? = text().takeUnless { it.isEmpty() } fun Element.ownTextOrNull(): String? = ownText().takeUnless { it.isEmpty() } + +fun Element.selectFirstParent(query: String): Element? { + val selector = QueryParser.parse(query) + val parents = parents() + val root = parents.lastOrNull() ?: return null + return parents.firstOrNull { + selector.matches(root, it) + } +}