feat: add tengxun category and batch helper

This commit is contained in:
Harold
2026-04-23 21:08:58 +08:00
parent 306a0d5bcc
commit c87f96d417
2 changed files with 121 additions and 0 deletions
+49
View File
@@ -21,6 +21,13 @@ HOME_HTML = """
</div>
"""
CATEGORY_HTML = """
<div class="list_item">
<a data-float="/x/cover/cid001/vid001.html"><img alt="三体" src="https://img.test/c.jpg"></a>
<a>更新至30集</a>
</div>
"""
class TestTencentSpider(unittest.TestCase):
def setUp(self):
@@ -71,6 +78,48 @@ class TestTencentSpider(unittest.TestCase):
},
)
@patch.object(Spider, "fetch")
def test_category_content_maps_filters_and_prefixes_channel(self, mock_fetch):
mock_fetch.return_value = SimpleNamespace(text=CATEGORY_HTML)
result = self.spider.categoryContent(
"tv",
"2",
False,
{
"sort": "18",
"iyear": "2024",
"year": "2024",
"type": "17",
"feature": "4",
"area": "2",
"itrailer": "1",
"sex": "1",
},
)
request_url = mock_fetch.call_args.args[0]
self.assertIn("channel=tv", request_url)
self.assertIn("offset=21", request_url)
self.assertIn("sort=18", request_url)
self.assertIn("iyear=2024", request_url)
self.assertIn("year=2024", request_url)
self.assertIn("itype=17", request_url)
self.assertIn("ifeature=4", request_url)
self.assertIn("iarea=2", request_url)
self.assertIn("itrailer=1", request_url)
self.assertIn("gender=1", request_url)
self.assertEqual(result["list"][0]["vod_id"], "tv$/x/cover/cid001/vid001.html")
self.assertEqual(result["page"], 2)
self.assertEqual(result["limit"], 21)
self.assertEqual(result["pagecount"], 9999)
@patch.object(Spider, "fetch")
def test_get_batch_video_info_parses_qzoutputjson_payload(self, mock_fetch):
mock_fetch.return_value = SimpleNamespace(
text='QZOutputJson={"results":[{"fields":{"vid":"vid001","title":"第1集","category_map":["0","正片"]}}]};'
)
result = self.spider._get_batch_video_info(["vid001"])
self.assertEqual(result, [{"vid": "vid001", "title": "第1集", "type": "正片"}])
if __name__ == "__main__":
unittest.main()
+72
View File
@@ -1,4 +1,5 @@
# coding=utf-8
import json
import re
import sys
@@ -74,3 +75,74 @@ class Spider(BaseSpider):
def playerContent(self, flag, id, vipFlags):
return {"parse": 1, "jx": 1, "url": id, "header": self._headers()}
def _safe_json(self, text, strip_prefix="", strip_suffix=""):
raw = str(text or "")
if strip_prefix and raw.startswith(strip_prefix):
raw = raw[len(strip_prefix):]
if strip_suffix and raw.endswith(strip_suffix):
raw = raw[: -len(strip_suffix)]
return json.loads(raw) if raw else {}
def _get_batch_video_info(self, vids):
results = []
for start in range(0, len(vids or []), 30):
batch = vids[start:start + 30]
if not batch:
continue
url = (
"https://union.video.qq.com/fcgi-bin/data?otype=json&tid=1804&appid=20001238"
"&appkey=6c03bbe9658448a4&union_platform=1&idlist=" + ",".join(batch)
)
response = self.fetch(url, headers=self._headers())
payload = self._safe_json(getattr(response, "text", ""), strip_prefix="QZOutputJson=", strip_suffix=";")
for item in payload.get("results", []):
fields = item.get("fields", {})
category_map = fields.get("category_map", [])
results.append(
{
"vid": fields.get("vid", ""),
"title": fields.get("title", ""),
"type": category_map[1] if len(category_map) > 1 else "",
}
)
return results
def categoryContent(self, tid, pg, filter, extend):
page = int(pg)
offset = (page - 1) * 21
params = [
"_all=1",
"append=1",
f"channel={tid}",
"listpage=1",
f"offset={offset}",
"pagesize=21",
"iarea=-1",
]
options = dict(extend or {})
if options.get("sort"):
params.append(f"sort={options['sort']}")
if options.get("iyear"):
params.append(f"iyear={options['iyear']}")
if options.get("year"):
params.append(f"year={options['year']}")
if options.get("type"):
params.append(f"itype={options['type']}")
if options.get("feature"):
params.append(f"ifeature={options['feature']}")
if options.get("area"):
params.append(f"iarea={options['area']}")
if options.get("itrailer"):
params.append(f"itrailer={options['itrailer']}")
if options.get("sex"):
params.append(f"gender={options['sex']}")
url = f"{self.base_host}/x/bu/pagesheet/list?" + "&".join(params)
response = self.fetch(url, headers=self._headers())
return {
"list": self._parse_list_items(getattr(response, "text", ""), with_channel=True, channel_id=str(tid)),
"page": page,
"pagecount": 9999,
"limit": 21,
"total": 999999,
}