diff --git a/py/tests/test_dbku.py b/py/tests/test_dbku.py index 0da31c3..472692a 100644 --- a/py/tests/test_dbku.py +++ b/py/tests/test_dbku.py @@ -95,6 +95,39 @@ class TestDBKUSpider(unittest.TestCase): self.assertEqual(result["list"][0]["vod_id"], "https://www.dbku.tv/voddetail/321.html") self.assertEqual(result["list"][0]["vod_name"], "搜索影片") + def test_parse_detail_page_extracts_meta_and_episodes(self): + html = """ +
+ +
+
+

独播剧

+

年份:2025

+

地区:大陆

+

导演:张三

+

主演:李四

+
+ 一段剧情简介 + 第1集 + 第2集 + """ + result = self.spider._parse_detail_page(html, "https://www.dbku.tv/voddetail/100.html") + vod = result["list"][0] + self.assertEqual(vod["vod_name"], "独播剧") + self.assertEqual(vod["vod_year"], "2025") + self.assertEqual(vod["vod_play_from"], "独播库") + self.assertIn("第1集$https://www.dbku.tv/vodplay/100-1-1.html", vod["vod_play_url"]) + + @patch.object(Spider, "_request_html") + def test_detail_content_reads_from_vod_id_url(self, mock_request_html): + mock_request_html.return_value = """ +

详情影片

+ 第1集 + """ + result = self.spider.detailContent(["https://www.dbku.tv/voddetail/200.html"]) + self.assertEqual(result["list"][0]["vod_id"], "https://www.dbku.tv/voddetail/200.html") + self.assertEqual(result["list"][0]["vod_name"], "详情影片") + if __name__ == "__main__": unittest.main() diff --git a/py/独播库.py b/py/独播库.py index 52935ec..448ca0e 100644 --- a/py/独播库.py +++ b/py/独播库.py @@ -1,4 +1,5 @@ # coding=utf-8 +import re import sys from urllib.parse import quote @@ -160,3 +161,54 @@ class Spider(BaseSpider): path = "/vodsearch/-------------.html?wd={0}&submit=".format(quote(key)) html = self._request_html(path, expect_xpath="//*[@id='searchList']|//*[contains(@class,'myui-vodlist__box')]") return self._page_result(self._parse_search_cards(html), pg) + + def _extract_text_by_prefix(self, html, prefixes): + texts = re.findall(r">([^<>]+)<", html) + for text in texts: + clean = text.strip() + for prefix in prefixes: + if clean.startswith(prefix): + return clean.split(":", 1)[-1].strip() + return "" + + def _parse_detail_page(self, html, vod_id): + root = self.html(html) + title = ((root.xpath("//*[contains(@class,'title')][1]//text()") or [""])[0]).strip() + pic = ( + (root.xpath("//*[contains(@class,'myui-content__thumb')]//img/@data-original") or [""])[0].strip() + or (root.xpath("//*[contains(@class,'myui-content__thumb')]//img/@src") or [""])[0].strip() + ) + content = "".join(root.xpath("//*[contains(@class,'data')][1]//text()")).strip() + + episodes = [] + seen = set() + for href, label in re.findall( + r']+href=["\']([^"\']*/vodplay/\d+-\d+-\d+\.html[^"\']*)["\'][^>]*>([\s\S]*?)', + html, + re.I, + ): + url = self._build_url(href) + name = re.sub(r"<[^>]*>", "", label).strip() + if not url or not name or "立即播放" in name or url in seen: + continue + seen.add(url) + episodes.append(f"{name}${url}") + + vod = { + "vod_id": vod_id, + "vod_name": title, + "vod_pic": self._build_url(pic), + "vod_year": self._extract_text_by_prefix(html, ["年份:"]), + "vod_area": self._extract_text_by_prefix(html, ["地区:"]), + "vod_actor": self._extract_text_by_prefix(html, ["主演:"]), + "vod_director": self._extract_text_by_prefix(html, ["导演:"]), + "vod_content": content, + "vod_play_from": "独播库", + "vod_play_url": "#".join(episodes), + } + return {"list": [vod]} + + def detailContent(self, ids): + vod_id = ids[0] + html = self._request_html(vod_id, expect_xpath="//*[contains(@class,'title')]|//a[contains(@href,'/vodplay/')]") + return self._parse_detail_page(html, vod_id)