Files
UHD_Media_Tool/packages/adapters/test/differential/detail.test.ts
T
rootandClaude Opus 5.5 92830c3ef3 fix(adapters): 观众详情页按真实页面适配(DET-2)
- 促销:详情 h1 是 font.free / font.halfdown 等 + 剩余时间 span[title],新增 umt.detail.promo 覆盖列表促销字段(以前一律判成无促销并覆盖列表的免费)
- 标题去掉 h1 里的「剩余时间:」;发布时间不再取标题区的促销到期时间
- 做种 / 下载 / 完成数、种子 Hash:umt.detail.fields.seeders / leechers / snatched / infoHash
- 副标题去掉评分徽标;标签只取最内层;上传者取 span.torrent-uploader-wrap,标签精确匹配(避开「发布者带宽」)
- 简介:去掉站点声明(page.descriptionStrip)与 MediaInfo 控件(codetop / show / hide),源码换行不再算一行
- 截图排除豆瓣海报与站点横幅
- 列表副标题改取 span.torrent-subtitle-text(以前前面粘着标签文字)
- 脱敏真实样本:详情 2 页进 differential/detail.test.ts,列表 1 页进 MP 差分

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-30 20:49:29 +08:00

97 lines
4.5 KiB
TypeScript

/**
* 详情页解析回归(DET-2):观众 audiences.me 真实详情页(2026-09-30 抓取,脱敏:只留标题栏与详情表,
* 去掉用户栏 / 评论 / 「行为」行的 downhash 下载链接 / 用户链接)。MP 通用 SiteSpider 不解析详情页,
* 没有 MP 期望可比;期望值按页面原文逐项人工核对。
*/
import { describe, expect, it } from "vitest";
import { audiencesDefinition } from "../../src/sites/index.ts";
import { parseDetailPage } from "../../src/sites/spider/detail.ts";
import { readInput } from "./diff-util.ts";
const OBSERVED = "2026-09-30T12:11:30.000Z";
const parse = (id: string) => {
const r = parseDetailPage(
readInput(`inputs/detail/rl-audiences-detail-${id}.html.txt`),
audiencesDefinition,
id,
OBSERVED,
);
expect(r.kind).toBe("ok");
return r.detail!;
};
describe("观众详情页(真实样本)", () => {
it("725858:原盘 DIY,50% 无期限,BDInfo", () => {
const d = parse("725858");
expect(d).toMatchObject({
title: "Rose 2026 1080p BluRay AVC DTS-HD MA 5.1-DIY@Audies",
// 副标题行右侧的豆瓣 / IMDb / 烂番茄 / Metacritic 评分不进副标题
subtitle: "罗斯 / 扑朔迷离的露丝(港)【德版原盘DIY 简繁字幕】",
category: { id: "401", name: "电影" },
sizeBytes: 23654532383,
seeders: 126,
leechers: 1,
snatched: 276,
promotion: { type: "50%", downloadFactor: 0.5, uploadFactor: 1, expiresAt: null },
hr: "unknown",
uploadedAt: "2026-09-27T09:25:07.000Z",
infoHash: "f7a77044521104ef2edafc0ab9bfc3774f763079",
imdbId: "tt25399154",
doubanId: "35322132",
tags: ["官方", "中字", "官字组", "DIY", "禁转"],
downloadUrl: "https://audiences.me/download.php?id=725858",
});
const p = d.page!;
expect(p.uploader).toBe("匿名");
expect(p.mediaInfo).toMatch(/^DISC INFO:\n\nDisc Label: {5}Rose\.2026/);
expect(p.mediaInfo).toContain("Presentation Graphics Chinese 15.892 kbps 繁体中文");
// 简介:没有站点声明、没有 BDInfo(页面上摘要 / 原文各一份)、行间没有多余空行
expect(p.descriptionText).toMatch(/^引用\n1\.原盘来自@4FR/);
expect(p.descriptionText).toContain("◎片  名 Rose\n◎年  代 2026\n");
expect(p.descriptionText).not.toMatch(/声明|DISC INFO|BDInfo/);
// 截图:豆瓣海报与站点横幅不算
expect(p.screenshots).toEqual([
"https://stor.picx.cx/images/2026/09/27/mvuGsV.jpg",
"https://stor.picx.cx/images/2026/09/27/mvuLud.jpg",
"https://stor.picx.cx/images/2026/09/27/mvuyvF.jpg",
"https://stor.picx.cx/images/2026/09/27/mvuTGH.jpg",
"https://stor.picx.cx/images/2026/09/27/mvu7AP.jpg",
]);
expect(p.tmdb).toBeNull();
// 文件清单不在页面上(点击后 AJAX 加载,端点未核对),暂不另发请求
expect(p.files).toEqual([]);
});
it("727077:WEB-DL 剧集,免费带到期,MediaInfo", () => {
const d = parse("727077");
expect(d).toMatchObject({
// h1 里「剩余时间:」文本节点不进标题
title: "A Prophet S01E16 2026 2160p iQIYI WEB-DL H265 HDR DDP5.1-ADWeb",
subtitle:
"我不是大师 第16集 | 类型:剧情 悬疑 | 主演:李现 李一桐 吴刚 刘冠麟 果靖霖 | 长风起 / 将相 / 江相 / 我是个算命先生",
category: { id: "402", name: "剧集" },
sizeBytes: 3575560274,
seeders: 319,
leechers: 12,
snatched: 407,
// 免费到期 2026-10-01 18:08:55(+08:00);发布时间 2026-09-30 18:08:55 不能被促销到期时间顶替
promotion: { type: "free", downloadFactor: 0, uploadFactor: 1, expiresAt: "2026-10-01T10:08:55.000Z" },
uploadedAt: "2026-09-30T10:08:55.000Z",
infoHash: "20183f7fe0b46b28f86a225871a2bdd0fd95e888",
imdbId: "tt36758489",
doubanId: "37297001",
tags: ["官方", "国语", "中字", "HDR10"],
});
const p = d.page!;
expect(p.mediaInfo).toMatch(/^General\nUnique ID {32}: 274676047450136587438060874497470881694/);
expect(p.mediaInfo).toContain(
"\nVideo\nID : 1\nFormat : HEVC\n",
);
// MediaInfo 控件的标题栏(文件名)与摘要表也不留在简介里
expect(p.descriptionText).not.toMatch(/GeneralVideoAudio|Unique ID|\.mkv$/m);
expect(p.descriptionText).toMatch(/^引用\n请不要转发此种至PTTime/);
expect(p.screenshots).toHaveLength(6);
expect(p.screenshots.some((u) => /poster|banner/.test(u))).toBe(false);
});
});