From d436b699a0b3e73fb1a5a785f11f70a587b6fd65 Mon Sep 17 00:00:00 2001 From: Harold <8866033@gmail.com> Date: Wed, 29 Apr 2026 15:26:36 +0800 Subject: [PATCH] feat: scaffold shuangxing spider --- py/tests/test_双星.py | 67 +++++++++++++++++++++++++++++++++++++ py/双星.py | 77 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 144 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..68efe0b --- /dev/null +++ b/py/tests/test_双星.py @@ -0,0 +1,67 @@ +import unittest +from importlib.machinery import SourceFileLoader +from pathlib import Path +from unittest.mock import patch + + +ROOT = Path(__file__).resolve().parents[1] +MODULE = SourceFileLoader("shuangxing_spider", str(ROOT / "双星.py")).load_module() +Spider = MODULE.Spider + + +class FakeResponse: + def __init__(self, status_code=200, text="", cookies=None): + self.status_code = status_code + self.text = text + self.cookies = cookies or {} + self.headers = {} + self.url = "" + + +class TestShuangXingSpider(unittest.TestCase): + def setUp(self): + Spider._instance = None + self.spider = Spider() + + def test_home_content_exposes_reference_categories(self): + content = self.spider.homeContent(False) + self.assertEqual( + [(item["type_id"], item["type_name"]) for item in content["class"]], + [ + ("ju", "国剧"), + ("zy", "综艺"), + ("mv", "电影"), + ("rh", "日韩"), + ("ym", "英美"), + ("wj", "外剧"), + ("dm", "动漫"), + ], + ) + + def test_home_video_content_returns_empty_list(self): + self.assertEqual(self.spider.homeVideoContent(), {"list": []}) + + @patch.object(Spider, "fetch") + def test_init_collects_cookie_pairs_and_headers_include_cookie(self, mock_fetch): + mock_fetch.return_value = FakeResponse(cookies={"foo": "bar", "token": "xyz"}) + self.spider.init() + self.assertEqual(self.spider.cookie, "foo=bar; token=xyz") + self.assertEqual(self.spider._headers()["cookie"], "foo=bar; token=xyz") + + def test_headers_without_cookie_keep_base_headers_only(self): + self.assertEqual( + self.spider._headers(), + { + "User-Agent": Spider.UA, + "Referer": Spider.BASE_URL, + }, + ) + + def test_detect_pan_type_returns_expected_keys(self): + self.assertEqual(self.spider._detect_pan_type("https://pan.quark.cn/s/demo"), "quark") + self.assertEqual(self.spider._detect_pan_type("https://www.alipan.com/s/demo"), "ali") + self.assertEqual(self.spider._detect_pan_type("https://example.com/video"), "") + + +if __name__ == "__main__": + unittest.main() diff --git a/py/双星.py b/py/双星.py new file mode 100644 index 0000000..16ee14d --- /dev/null +++ b/py/双星.py @@ -0,0 +1,77 @@ +# coding=utf-8 +import sys + +from base.spider import Spider as BaseSpider + +sys.path.append("..") + + +class Spider(BaseSpider): + BASE_URL = "https://1.star2.cn" + UA = ( + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " + "AppleWebKit/537.36 (KHTML, like Gecko) " + "Chrome/143.0.0.0 Safari/537.36 Edg/143.0.0.0" + ) + CATEGORIES = [ + ("ju", "国剧"), + ("zy", "综艺"), + ("mv", "电影"), + ("rh", "日韩"), + ("ym", "英美"), + ("wj", "外剧"), + ("dm", "动漫"), + ] + + def __init__(self): + self.name = "双星" + self.cookie = "" + + def init(self, extend=""): + response = self.fetch( + self.BASE_URL, + headers={"User-Agent": self.UA, "Referer": self.BASE_URL}, + allow_redirects=False, + timeout=15, + ) + if response.status_code != 200: + return None + self.cookie = "; ".join([f"{name}={value}" for name, value in dict(response.cookies).items()]) + return None + + def getName(self): + return self.name + + def homeContent(self, filter): + return {"class": [{"type_id": type_id, "type_name": type_name} for type_id, type_name in self.CATEGORIES]} + + def homeVideoContent(self): + return {"list": []} + + def _headers(self): + headers = {"User-Agent": self.UA, "Referer": self.BASE_URL} + if self.cookie: + headers["cookie"] = self.cookie + return headers + + def _detect_pan_type(self, link): + text = str(link or "").strip().lower() + if "quark" in text: + return "quark" + if "115.com" in text: + return "115" + if "cloud.189.cn" in text: + return "tianyi" + if "drive.uc.cn" in text or "uc.cn" in text: + return "uc" + if "pan.baidu.com" in text: + return "baidu" + if "xunlei" in text: + return "xunlei" + if "123pan" in text: + return "123pan" + if "caiyun" in text or "139.com" in text: + return "yd" + if "aliyundrive" in text or "alipan" in text: + return "ali" + return ""