feat: scaffold dbku spider parsing
This commit is contained in:
@@ -0,0 +1,43 @@
|
|||||||
|
import unittest
|
||||||
|
from importlib.machinery import SourceFileLoader
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
|
MODULE = SourceFileLoader("dbku_spider", str(ROOT / "独播库.py")).load_module()
|
||||||
|
Spider = MODULE.Spider
|
||||||
|
|
||||||
|
|
||||||
|
class TestDBKUSpider(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.spider = Spider()
|
||||||
|
self.spider.init()
|
||||||
|
|
||||||
|
def test_home_content_exposes_expected_categories(self):
|
||||||
|
content = self.spider.homeContent(False)
|
||||||
|
class_ids = [item["type_id"] for item in content["class"]]
|
||||||
|
self.assertEqual(class_ids, ["index", "movie", "variety", "anime", "hk", "luju"])
|
||||||
|
|
||||||
|
def test_parse_list_cards_extracts_detail_url_title_cover_and_description(self):
|
||||||
|
html = """
|
||||||
|
<div class="myui-vodlist__box">
|
||||||
|
<a class="thumb" href="/voddetail/123.html" title="示例影片" data-original="https://img.example/dbku.jpg"></a>
|
||||||
|
<span class="pic-text">更新至10集</span>
|
||||||
|
</div>
|
||||||
|
"""
|
||||||
|
cards = self.spider._parse_list_cards(html)
|
||||||
|
self.assertEqual(
|
||||||
|
cards,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"vod_id": "https://www.dbku.tv/voddetail/123.html",
|
||||||
|
"vod_name": "示例影片",
|
||||||
|
"vod_pic": "https://img.example/dbku.jpg",
|
||||||
|
"vod_remarks": "更新至10集",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
# coding=utf-8
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from base.spider import Spider as BaseSpider
|
||||||
|
|
||||||
|
sys.path.append("..")
|
||||||
|
|
||||||
|
|
||||||
|
class Spider(BaseSpider):
|
||||||
|
def __init__(self):
|
||||||
|
self.name = "独播库"
|
||||||
|
self.host = "https://www.dbku.tv"
|
||||||
|
self.headers = {
|
||||||
|
"User-Agent": (
|
||||||
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
|
||||||
|
"AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||||
|
"Chrome/124.0.0.0 Safari/537.36"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
self.categories = [
|
||||||
|
{"type_name": "连续剧", "type_id": "index"},
|
||||||
|
{"type_name": "电影", "type_id": "movie"},
|
||||||
|
{"type_name": "综艺", "type_id": "variety"},
|
||||||
|
{"type_name": "动漫", "type_id": "anime"},
|
||||||
|
{"type_name": "港剧", "type_id": "hk"},
|
||||||
|
{"type_name": "陆剧", "type_id": "luju"},
|
||||||
|
]
|
||||||
|
|
||||||
|
def init(self, extend=""):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def getName(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
def homeContent(self, filter):
|
||||||
|
return {"class": self.categories}
|
||||||
|
|
||||||
|
def homeVideoContent(self):
|
||||||
|
return {"list": []}
|
||||||
|
|
||||||
|
def _build_url(self, href):
|
||||||
|
raw = str(href or "").strip()
|
||||||
|
if not raw:
|
||||||
|
return ""
|
||||||
|
if raw.startswith(("http://", "https://")):
|
||||||
|
return raw
|
||||||
|
if raw.startswith("//"):
|
||||||
|
return "https:" + raw
|
||||||
|
if raw.startswith("/"):
|
||||||
|
return self.host + raw
|
||||||
|
return self.host + "/" + raw
|
||||||
|
|
||||||
|
def _parse_list_cards(self, html):
|
||||||
|
root = self.html(html)
|
||||||
|
results = []
|
||||||
|
if root is None:
|
||||||
|
return results
|
||||||
|
|
||||||
|
cards = root.xpath("//*[contains(@class,'myui-vodlist__box')]")
|
||||||
|
seen = set()
|
||||||
|
for card in cards:
|
||||||
|
href = ""
|
||||||
|
title = ""
|
||||||
|
pic = ""
|
||||||
|
for anchor in card.xpath(".//a[@href]"):
|
||||||
|
raw_href = (anchor.xpath("./@href") or [""])[0].strip()
|
||||||
|
if "/voddetail/" in raw_href:
|
||||||
|
href = self._build_url(raw_href)
|
||||||
|
title = (
|
||||||
|
(anchor.xpath("./@title") or [""])[0].strip()
|
||||||
|
or "".join(anchor.xpath(".//text()")).strip()
|
||||||
|
)
|
||||||
|
pic = (
|
||||||
|
(anchor.xpath("./@data-original") or [""])[0].strip()
|
||||||
|
or (anchor.xpath("./@src") or [""])[0].strip()
|
||||||
|
)
|
||||||
|
break
|
||||||
|
if not href or href in seen or not title:
|
||||||
|
continue
|
||||||
|
|
||||||
|
remarks = "".join(card.xpath(".//*[contains(@class,'pic-text')][1]//text()")).strip()
|
||||||
|
seen.add(href)
|
||||||
|
results.append(
|
||||||
|
{
|
||||||
|
"vod_id": href,
|
||||||
|
"vod_name": title,
|
||||||
|
"vod_pic": self._build_url(pic),
|
||||||
|
"vod_remarks": remarks,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return results
|
||||||
Reference in New Issue
Block a user