From b6a44611f1576cc6a7a6bd2b0143800cea65c078 Mon Sep 17 00:00:00 2001 From: Harold <8866033@gmail.com> Date: Sun, 19 Apr 2026 16:40:02 +0800 Subject: [PATCH] feat: scaffold ddys spider --- py/tests/test_低端影视.py | 41 ++++++++++++++++ py/低端影视.py | 101 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 py/tests/test_低端影视.py create mode 100644 py/低端影视.py diff --git a/py/tests/test_低端影视.py b/py/tests/test_低端影视.py new file mode 100644 index 0000000..054e3f2 --- /dev/null +++ b/py/tests/test_低端影视.py @@ -0,0 +1,41 @@ +import unittest +from importlib.machinery import SourceFileLoader +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[1] +MODULE = SourceFileLoader("ddys_spider", str(ROOT / "低端影视.py")).load_module() +Spider = MODULE.Spider + + +class TestDDYSSpider(unittest.TestCase): + def setUp(self): + Spider._instance = None + self.spider = Spider() + self.spider.init() + + def test_home_content_exposes_expected_classes_and_filter_keys(self): + content = self.spider.homeContent(False) + self.assertEqual( + [item["type_id"] for item in content["class"]], + ["series", "movie", "variety", "anime"], + ) + self.assertEqual( + [item["key"] for item in content["filters"]["movie"]], + ["class", "area", "year", "by"], + ) + + def test_home_video_content_returns_empty_list(self): + self.assertEqual(self.spider.homeVideoContent(), {"list": []}) + + def test_build_category_url_applies_default_and_selected_filters(self): + url = self.spider._build_category_url("movie", "2", {"class": "/genre/action", "year": "/year/2025"}) + self.assertEqual(url, "https://ddys.io/movie/genre/action/year/2025/page/2") + + def test_build_category_url_for_first_page_keeps_page_segment(self): + url = self.spider._build_category_url("series", "1", {}) + self.assertEqual(url, "https://ddys.io/series/page/1") + + +if __name__ == "__main__": + unittest.main() diff --git a/py/低端影视.py b/py/低端影视.py new file mode 100644 index 0000000..8c99b79 --- /dev/null +++ b/py/低端影视.py @@ -0,0 +1,101 @@ +# coding=utf-8 +import json +import sys + +from base.spider import Spider as BaseSpider + +sys.path.append("..") + + +class Spider(BaseSpider): + def __init__(self): + self.name = "低端影视" + self.host = "https://ddys.io" + self.headers = { + "User-Agent": ( + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) " + "AppleWebKit/537.36 (KHTML, like Gecko) " + "Chrome/145.0.0.0 Safari/537.36" + ), + "Referer": self.host + "/", + } + self.classes = [ + {"type_id": "series", "type_name": "剧集"}, + {"type_id": "movie", "type_name": "电影"}, + {"type_id": "variety", "type_name": "综艺"}, + {"type_id": "anime", "type_name": "动漫"}, + ] + self.filter_def = { + "movie": {"cateId": "movie"}, + "series": {"cateId": "series"}, + "variety": {"cateId": "variety"}, + "anime": {"cateId": "anime"}, + } + self.filters = { + key: [ + {"key": "class", "name": "剧情", "init": "", "value": [{"n": "全部", "v": ""}]}, + {"key": "area", "name": "地区", "init": "", "value": [{"n": "全部", "v": ""}]}, + {"key": "year", "name": "年份", "init": "", "value": [{"n": "全部", "v": ""}]}, + { + "key": "by", + "name": "排序", + "init": "", + "value": [ + {"n": "时间", "v": ""}, + {"n": "评分", "v": "rating/"}, + {"n": "热门", "v": "popular/"}, + ], + }, + ] + for key in ["movie", "series", "variety", "anime"] + } + + def init(self, extend=""): + return None + + def getName(self): + return self.name + + def homeContent(self, filter): + return {"class": self.classes, "filters": self.filters} + + def homeVideoContent(self): + return {"list": []} + + def _stringify(self, value): + return "" if value is None else str(value) + + def _normalize_ext(self, extend): + if isinstance(extend, dict): + return extend + if not extend: + return {} + try: + return json.loads(str(extend)) + except Exception: + return {} + + def _build_url(self, path): + raw = self._stringify(path).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 _build_category_url(self, tid, pg, extend): + values = dict(self.filter_def.get(str(tid), {"cateId": str(tid)})) + values.update(self._normalize_ext(extend)) + path = ( + f"{values.get('by', '')}" + f"{values.get('cateId', tid)}" + f"{values.get('class', '')}" + f"{values.get('area', '')}" + f"{values.get('year', '')}" + f"/page/{int(pg)}" + ) + return self._build_url(path)