fix: TvcatHandler搜索和详情用HttpURLConnection替代Jsoup下载,绕过Jsoup默认UA被反爬拦截
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
package com.videoapp.tv.engine.tvcat
|
package com.videoapp.tv.engine.tvcat
|
||||||
|
|
||||||
|
import com.videoapp.tv.data.SearchResult
|
||||||
import com.videoapp.tv.data.SiteConfig
|
import com.videoapp.tv.data.SiteConfig
|
||||||
import com.videoapp.tv.engine.BaseSourceHandler
|
import com.videoapp.tv.engine.BaseSourceHandler
|
||||||
import com.videoapp.tv.engine.Episode
|
import com.videoapp.tv.engine.Episode
|
||||||
@@ -8,7 +9,9 @@ import kotlinx.coroutines.Dispatchers
|
|||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
|
import java.net.HttpURLConnection
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
|
import java.net.URLEncoder
|
||||||
|
|
||||||
class TvcatHandler : BaseSourceHandler(
|
class TvcatHandler : BaseSourceHandler(
|
||||||
id = "tvcat",
|
id = "tvcat",
|
||||||
@@ -33,12 +36,84 @@ class TvcatHandler : BaseSourceHandler(
|
|||||||
videoSelector = "video source, video[src]"
|
videoSelector = "video source, video[src]"
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
|
override suspend fun search(
|
||||||
|
keyword: String,
|
||||||
|
onResult: suspend (List<SearchResult>) -> Unit,
|
||||||
|
onError: suspend (String) -> Unit
|
||||||
|
) {
|
||||||
|
try {
|
||||||
|
val results = withContext(Dispatchers.IO) {
|
||||||
|
val encoded = URLEncoder.encode(keyword, "UTF-8")
|
||||||
|
val searchUrl = "https://tvcat.cc/search?q=$encoded"
|
||||||
|
val conn = URL(searchUrl).openConnection() as HttpURLConnection
|
||||||
|
conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
|
||||||
|
conn.setRequestProperty("Accept-Language", "zh-CN,zh;q=0.9")
|
||||||
|
conn.connectTimeout = 15000
|
||||||
|
conn.readTimeout = 15000
|
||||||
|
val html = if (conn.responseCode == 200) {
|
||||||
|
conn.inputStream.bufferedReader().use { it.readText() }
|
||||||
|
} else ""
|
||||||
|
conn.disconnect()
|
||||||
|
|
||||||
|
if (html.isEmpty()) return@withContext emptyList<SearchResult>()
|
||||||
|
|
||||||
|
val doc = Jsoup.parse(html)
|
||||||
|
val items = doc.select("li.col-md-2.col-sm-3.col-4")
|
||||||
|
val resultsList = mutableListOf<SearchResult>()
|
||||||
|
|
||||||
|
for (item in items) {
|
||||||
|
try {
|
||||||
|
val titleEl = item.selectFirst("a[title]") ?: continue
|
||||||
|
val linkEl = item.selectFirst("a")
|
||||||
|
val coverEl = item.selectFirst("img")
|
||||||
|
val categoryEl = item.selectFirst(".text-muted")
|
||||||
|
|
||||||
|
val title = titleEl.text().trim()
|
||||||
|
val detailUrl = buildFullUrl(linkEl?.attr("href")?.trim() ?: "")
|
||||||
|
val coverUrl = buildFullUrl(coverEl?.attr("src")?.trim() ?: "")
|
||||||
|
val category = categoryEl?.text()?.trim() ?: ""
|
||||||
|
|
||||||
|
if (title.isNotEmpty() && detailUrl.isNotEmpty()) {
|
||||||
|
resultsList.add(
|
||||||
|
SearchResult(
|
||||||
|
title = title,
|
||||||
|
coverUrl = coverUrl,
|
||||||
|
detailUrl = detailUrl,
|
||||||
|
category = category,
|
||||||
|
date = ""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} catch (_: Exception) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resultsList
|
||||||
|
}
|
||||||
|
|
||||||
|
if (results.isEmpty()) {
|
||||||
|
onError("未找到结果")
|
||||||
|
} else {
|
||||||
|
onResult(results)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
onError("搜索失败: ${e.message}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun extractVideos(detailUrl: String): List<PlaySource> =
|
override suspend fun extractVideos(detailUrl: String): List<PlaySource> =
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
val doc = Jsoup.connect(detailUrl)
|
val conn = URL(detailUrl).openConnection() as HttpURLConnection
|
||||||
.header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
|
conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")
|
||||||
.header("Accept-Language", "zh-CN,zh;q=0.9")
|
conn.setRequestProperty("Accept-Language", "zh-CN,zh;q=0.9")
|
||||||
.timeout(15000).get()
|
conn.connectTimeout = 15000
|
||||||
|
conn.readTimeout = 15000
|
||||||
|
val html = if (conn.responseCode == 200) {
|
||||||
|
conn.inputStream.bufferedReader().use { it.readText() }
|
||||||
|
} else ""
|
||||||
|
conn.disconnect()
|
||||||
|
if (html.isEmpty()) return@withContext emptyList()
|
||||||
|
|
||||||
|
val doc = Jsoup.parse(html)
|
||||||
val episodes = doc.select("li.list-inline-item a").mapNotNull { ep ->
|
val episodes = doc.select("li.list-inline-item a").mapNotNull { ep ->
|
||||||
val title = ep.text().trim()
|
val title = ep.text().trim()
|
||||||
val href = ep.attr("href").trim()
|
val href = ep.attr("href").trim()
|
||||||
|
|||||||
Reference in New Issue
Block a user