From e91f41b0480df679afd6a52f91d1670c79ccc195 Mon Sep 17 00:00:00 2001 From: Harold <8866033@gmail.com> Date: Mon, 20 Apr 2026 15:41:05 +0800 Subject: [PATCH] feat: scaffold rrdy spider --- py/tests/test_人人电影.py | 49 ++++++++++++++++++++++++ py/人人电影.py | 80 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 129 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..6e8861f --- /dev/null +++ b/py/tests/test_人人电影.py @@ -0,0 +1,49 @@ +import unittest +from importlib.machinery import SourceFileLoader +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[1] +MODULE = SourceFileLoader("rrdy_spider", str(ROOT / "人人电影.py")).load_module() +Spider = MODULE.Spider + + +class TestRenRenDianYingSpider(unittest.TestCase): + def setUp(self): + Spider._instance = None + self.spider = Spider() + self.spider.init() + + 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"]], + [ + ("movie/list_2", "电影"), + ("dianshiju/list_6", "电视剧"), + ("dongman/list_13", "动漫"), + ("zongyi/list_10", "老电影"), + ], + ) + + def test_home_video_content_returns_empty_list(self): + self.assertEqual(self.spider.homeVideoContent(), {"list": []}) + + def test_build_url_and_pan_detection_helpers(self): + self.assertEqual(self.spider._build_url("/movie/1.html"), "https://www.rrdynb.com/movie/1.html") + self.assertEqual( + self.spider._build_url("https://pan.baidu.com/s/demo"), + "https://pan.baidu.com/s/demo", + ) + self.assertTrue(self.spider._is_supported_pan_url("https://pan.baidu.com/s/demo")) + self.assertTrue(self.spider._is_supported_pan_url("https://pan.quark.cn/s/demo")) + self.assertFalse(self.spider._is_supported_pan_url("https://pan.xunlei.com/s/demo")) + + def test_clean_search_title_and_normalize_title(self): + self.assertEqual( + self.spider._clean_search_title("剑来 第二季"), + "剑来 第二季", + ) + self.assertEqual(self.spider._normalize_title("《繁花》"), "繁花") + self.assertEqual(self.spider._normalize_title("「诛仙」特别篇"), "诛仙") + self.assertEqual(self.spider._normalize_title("普通标题"), "普通标题") diff --git a/py/人人电影.py b/py/人人电影.py new file mode 100644 index 0000000..0458c66 --- /dev/null +++ b/py/人人电影.py @@ -0,0 +1,80 @@ +# coding=utf-8 +import re +import sys +from urllib.parse import urljoin + +from base.spider import Spider as BaseSpider + +sys.path.append("..") + + +class Spider(BaseSpider): + def __init__(self): + self.name = "人人电影" + self.host = "https://www.rrdynb.com" + self.headers = { + "User-Agent": ( + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " + "AppleWebKit/537.36 (KHTML, like Gecko) " + "Chrome/136.0.0.0 Safari/537.36" + ), + "Referer": self.host + "/", + } + self.categories = [ + {"type_id": "movie/list_2", "type_name": "电影"}, + {"type_id": "dianshiju/list_6", "type_name": "电视剧"}, + {"type_id": "dongman/list_13", "type_name": "动漫"}, + {"type_id": "zongyi/list_10", "type_name": "老电影"}, + ] + self.supported_pan_patterns = [ + r"pan\.baidu\.com|yun\.baidu\.com", + r"pan\.quark\.cn", + r"drive\.uc\.cn", + r"115\.com", + r"123pan\.com|123684\.com|123865\.com|123912\.com", + r"cloud\.189\.cn", + r"yun\.139\.com", + ] + self.excluded_pan_patterns = [ + r"pan\.xunlei\.com", + r"aliyundrive\.com", + r"alipan\.com", + ] + + 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, path): + raw = str(path or "").strip() + if not raw: + return "" + if raw.startswith(("http://", "https://")): + return raw + return urljoin(self.host + "/", raw) + + def _clean_search_title(self, text): + return str(text or "").replace("", "").replace("", "").strip() + + def _normalize_title(self, raw_title): + cleaned = self._clean_search_title(raw_title) + matched = re.search(r"《(.*?)》|「(.*?)」", cleaned) + if matched: + return (matched.group(1) or matched.group(2) or "").strip() + return cleaned.strip() + + def _is_supported_pan_url(self, url): + raw = str(url or "").strip() + if not raw: + return False + if any(re.search(pattern, raw, re.I) for pattern in self.excluded_pan_patterns): + return False + return any(re.search(pattern, raw, re.I) for pattern in self.supported_pan_patterns)