fix(sites): 憨憨详情页按真实结构解析豆瓣块与 MediaInfo
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
df22200bfd
commit
653bdcb976
6 files changed
+71
-6
No files matched your search
@@ -4,6 +4,9 @@
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### 修复
|
||||
- 憨憨详情页(按 2026-10-02 真实页面):豆瓣信息一项一行,去掉分隔线、空值项、重复的标题行和「该信息最后更新」提示;MediaInfo 只取原文,不再混进摘要表。已缓存的详情在过期或手动刷新后生效。
|
||||
|
||||
## [0.3.18] - 2026-10-02
|
||||
|
||||
## [0.3.17] - 2026-10-02
|
||||
|
||||
@@ -264,7 +264,9 @@
|
||||
},
|
||||
"page": {
|
||||
"labelSelectors": ["div.font-bold.leading-6", "span.font-bold"],
|
||||
"fileListPath": "viewfilelist.php?id={id}"
|
||||
"fileListPath": "viewfilelist.php?id={id}",
|
||||
"mediaInfo": "#mediainfo-raw",
|
||||
"descriptionStrip": "div.mt-5, div.flex.flex-row.items-center"
|
||||
}
|
||||
},
|
||||
"vipLevels": ["贵宾", "VIP"],
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { HHANCLUB_DETAIL_PAGE_2026, HHANCLUB_DETAIL_PAGE_FULL, HHANCLUB_FILELIST_FRAGMENT } from "@umt/testkit";
|
||||
import {
|
||||
HHANCLUB_DETAIL_PAGE_2026,
|
||||
HHANCLUB_DETAIL_PAGE_FULL,
|
||||
HHANCLUB_DETAIL_PAGE_REAL_2026,
|
||||
HHANCLUB_FILELIST_FRAGMENT,
|
||||
} from "@umt/testkit";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { hhanclubDefinition } from "../definitions/index.ts";
|
||||
import { looksLikeMediaInfo, pageFromBbcode } from "../detail-text.ts";
|
||||
@@ -109,6 +114,30 @@ Format : AVC[/quote]
|
||||
});
|
||||
});
|
||||
|
||||
describe("憨憨真实详情页(2026-10-02 摘录)", () => {
|
||||
const { detail } = parseDetailPage(HHANCLUB_DETAIL_PAGE_REAL_2026, hhanclubDefinition, "219860", OBSERVED);
|
||||
const page = detail!.page!;
|
||||
|
||||
it("MediaInfo 只取 #mediainfo-raw 原文,不带摘要表", () => {
|
||||
expect(page.mediaInfo!.startsWith("General\nComplete name")).toBe(true);
|
||||
expect(page.mediaInfo).not.toContain("体 积");
|
||||
});
|
||||
|
||||
it("豆瓣块一项一行;去掉分隔线、空值项、标题行与更新提示;链接之间已有逗号不再补分隔", () => {
|
||||
const t = page.descriptionText!;
|
||||
expect(t.split("\n").slice(0, 3)).toEqual([
|
||||
"片名: 斗罗大陆Ⅱ绝世唐门 年番1",
|
||||
"别名: 斗罗大陆2,斗罗大陆2:绝世唐门\u200e,斗罗大陆2绝世唐门,绝世唐门动画版",
|
||||
"年代: 2023",
|
||||
]);
|
||||
expect(t).toContain("\n导演: 沈乐平 Leping Shen\n");
|
||||
expect(t).toContain("编剧: 沈乐平 Leping Shen,唐家三少 Wei Zhang");
|
||||
expect(t).toContain("主演:\n梁达伟 Dawei Liang / 蒋丽 Li Jiang");
|
||||
expect(t).not.toMatch(/-{5,}|标语|该信息最后更新|\(23691\)/);
|
||||
expect(page.doubanId).toBe("35567787");
|
||||
});
|
||||
});
|
||||
|
||||
describe("详情页扩展内容(憨憨 2026 真实结构:分节 div,无 #kdescr)", () => {
|
||||
const { kind, detail } = parseDetailPage(HHANCLUB_DETAIL_PAGE_2026, hhanclubDefinition, "91003", OBSERVED);
|
||||
const page = detail!.page!;
|
||||
|
||||
@@ -220,16 +220,38 @@ export function extractDetailPage($: CheerioAPI, conf: DetailConf, base: string)
|
||||
} else if (infoBlock) {
|
||||
const c = infoBlock.clone();
|
||||
c.find("img").remove();
|
||||
if (p.descriptionStrip) c.find(p.descriptionStrip).remove();
|
||||
// 块里的「标签」span 与值之间补上冒号 / 换行,读起来是「片名:xxx」一行一项
|
||||
// (换行要用 BR 占位:源码里的换行在 blockText 里按空白处理)
|
||||
// 站点排版用的分隔线(憨憨是行内 font):换成换行
|
||||
c.find("font, span, div")
|
||||
.filter((_, x) => /^[-=_—]{5,}$/.test($(x).text().trim()))
|
||||
.replaceWith(BR);
|
||||
c.find(p.labelSelectors?.join(", ") || "span.font-bold").each((_, n) => {
|
||||
const e = $(n);
|
||||
const t = e.text().trim();
|
||||
// 空值的项(憨憨「标语:」)整项去掉
|
||||
const v = e.next();
|
||||
if (v.length && !v.text().trim() && !v.find("img").length) {
|
||||
(e.parent().children().length === 2 ? e.parent() : e).remove();
|
||||
v.remove();
|
||||
return;
|
||||
}
|
||||
if (t && t.length <= 16 && !/[::]$/.test(t)) e.text(`${t}:`);
|
||||
e.before("\n");
|
||||
e.before(BR);
|
||||
});
|
||||
// 并排的演职员链接之间补分隔(之间已有逗号等文字的不补)
|
||||
c.find("a + a").each((_, n) => {
|
||||
const prev = n.prev;
|
||||
if (prev && prev.type === "text" && prev.data.trim()) return;
|
||||
$(n).before(" / ");
|
||||
});
|
||||
const t = blockText($, c)
|
||||
.replace(/[ \t]{2,}/g, " ")
|
||||
.replace(/[ \t]*\n[ \t]*/g, "\n")
|
||||
.replace(/:\s*\n(?=\S)/g, ":");
|
||||
.replace(/\n{3,}/g, "\n\n")
|
||||
.replace(/:\s*\n(?=\S)/g, ":")
|
||||
.trim();
|
||||
if (t) page.descriptionText = t.slice(0, 20_000);
|
||||
}
|
||||
|
||||
|
||||
@@ -154,3 +154,10 @@ export const HHANCLUB_FILELIST_FRAGMENT = `<table class="main" border="1" cellsp
|
||||
<tr><td class="rowfollow">Example.Show.S01E18.2026.2160p.mkv</td><td class="rowfollow" align="right">5.04 GB</td></tr>
|
||||
<tr><td class="rowfollow">Example.Show.S01E19.2026.2160p.mkv</td><td class="rowfollow" align="right">4.98 GB</td></tr>
|
||||
</table>`;
|
||||
|
||||
/**
|
||||
* 2026-10-02 真实详情页(219860)摘录:MediaInfo 一节(#mediainfo-info 摘要 + #mediainfo-raw 原文,原文截前 25 行)
|
||||
* 与海报、豆瓣两节,原样保留标签结构;页面其余部分(含下载链接 passkey、用户链接)未收录。
|
||||
*/
|
||||
export const HHANCLUB_DETAIL_PAGE_REAL_2026 =
|
||||
'<!DOCTYPE html><html><head><title>HHCLUB :: 种子详情</title></head><body>\n<div id="user-info-panel"><a href="userdetails.php?id=7">bob</a> <a href="logout.php">退出</a></div>\n<div class="grid grid-cols-[80px_1fr]">\n<div onclick=\'slideInfo()\' class=\'cursor-pointer flex items-start leading-6 gap-x-1 font-bold\'><div class=\'flex items-center gap-x-1\'>MediaInfo</div></div><div class=\'w-full\'><div id="mediainfo-info"><pre><code class="gap-y-1 flex flex-col"><div class=\'flex gap-y-5 text-[13px]\'><span class=\'w-[60px]\'>文件名:</span><span>斗罗大陆Ⅱ绝世唐门.Soul.Land.2.The.Peerless.Tang.Clan.S01E173.2023.2160p.WEB-DL.H.265.AAC2.0-HHWEB.mp4</span></div><div class="grid gap-y-1"><div class="text-[13px] grid grid-cols-[60px,1fr]"><span class="w-[100px] ">体 积: </span><span>1.20 GiB</span></div><div class="text-[13px] grid grid-cols-[60px,1fr]"><span class="w-[100px] ">时 长: </span><span>21 min 52 s</span></div><div class="text-[13px] grid grid-cols-[60px,1fr]"><span class="w-[100px] ">分辨率: </span><span>3 840 pixels x 2 160 pixels</span></div><div class="text-[13px] grid grid-cols-[60px,1fr]"><span class="w-[100px] ">码 率: </span><span>7 701 kb/s</span></div><div class="text-[13px] grid grid-cols-[60px,1fr]"><span class="w-[100px] ">帧 率: </span><span>30.000 FPS</span></div></div><div class=\'flex gap-y-5 text-[13px]\'><span class=\'w-[60px]\'>音 频: </span><span class=\'flex flex-col max-h-[175px] flex-wrap gap-x-10\'><div class="text-[13px]"><span >01: </span><span>AAC LC 2 channels 125 kb/s</span></div></span></div></code></pre></div><div id="mediainfo-raw" class="hidden text-[13px]"><pre><code>General\nComplete name : 斗罗大陆Ⅱ绝世唐门.Soul.Land.2.The.Peerless.Tang.Clan.S01E173.2023.2160p.WEB-DL.H.265.AAC2.0-HHWEB.mp4\nFormat : MPEG-4\nFormat profile : Base Media\nCodec ID : isom (isom/iso2/mp41)\nFile size : 1.20 GiB\nDuration : 21 min 52 s\nOverall bit rate mode : Variable\nOverall bit rate : 7 837 kb/s\nWriting application : Lavf60.10.100\nVideo\nID : 1\nFormat : HEVC\nFormat/Info : High Efficiency Video Coding\nFormat profile : Main@L5@Main\nCodec ID : hev1\nCodec ID/Info : High Efficiency Video Coding\nDuration : 21 min 52 s\nSource duration : 21 min 52 s\nBit rate : 7 701 kb/s\nWidth : 3 840 pixels\nHeight : 2 160 pixels\nDisplay aspect ratio : 16:9\nFrame rate mode : Variable</code></pre></div></div><div class=\'leading-6 font-bold cursor-pointer\' onclick=\'slideThis(`cover`)\'><div class=\'flex items-center gap-x-3\'><img id=\'cover-is-fold-img\' class=\'w-3 h-3 \' alt=\'展开缩进\' src=\'styles/HHan/icons/fold-1.svg\'>海报</div></div><div class=\'w-full border-[1px] border-gray-400 rounded-md border-no leading-6 font-medium text-left break-all\'>\n <img id=\'cover-content\' class=\' h-[450px] !rounded-md m-4\' alt=\'海报\' src=\'https://proxy-cover.hhanclub.net/douban/p2877604309.jpg\'>\n </div> <div class="font-bold leading-6 cursor-pointer" onclick="slideThis(\'douban_info\')">\n <div class="flex items-center gap-x-3">\n <img id=\'douban_info-is-fold-img\' class=\'w-3 h-3 \' alt=\'展开缩进\'\n src=\'styles/HHan/icons/fold-1.svg\'>\n 豆瓣\n </div>\n </div> <div class="border-[1px] w-full border-gray-400 p-[15px] rounded-md">\n <div class="flex flex-row items-center gap-x-1">\n <img src="styles/HHan/icons/icon-douban.svg" alt="豆瓣">\n <a class="!text-blue-400 text-base" target="_blank"\n href="https://movie.douban.com/subject/35567787">斗罗大陆Ⅱ绝世唐门 年番1</a>\n <div class="text-gray-400 text-base">2023</div>\n <div class="text-gray-400 text-base">电视剧</div>\n <div class="text-xl font-bold text-green-500">7.7</div>\n <div class="text-gray-500 text-base">(23691)\n </div>\n </div>\n <div id="douban_info-content" class="flex flex-row w-full justify-between ">\n <div class="flex flex-col break-all flex-1">\n <font color="naLine truncated
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"$comment": "HHClub 分类名取自 MovieClaw hhanclub.yaml 注释(导航栏分类表);REQ §4.5 要求综艺/体育/短剧保留原始分类。2026-09-29 真实账号核对:列表标题链接里带站点的新种标记「[新]」(详情页标题没有),用 replace 过滤掉;等级「贵宾」为 VIP;访问默认按低频原则收紧(快照只抓第 1 页、健康检测 6 小时、详情缓存 24 小时、搜索并发 1)。 2026-10-02 真实列表页核对:标签在 torrent-title 里的 span.tag(促销是 promotion-tag,不混入)。",
|
||||
"$comment": "HHClub 分类名取自 MovieClaw hhanclub.yaml 注释(导航栏分类表);REQ §4.5 要求综艺/体育/短剧保留原始分类。2026-09-29 真实账号核对:列表标题链接里带站点的新种标记「[新]」(详情页标题没有),用 replace 过滤掉;等级「贵宾」为 VIP;访问默认按低频原则收紧(快照只抓第 1 页、健康检测 6 小时、详情缓存 24 小时、搜索并发 1)。 2026-10-02 真实列表页核对:标签在 torrent-title 里的 span.tag(促销是 promotion-tag,不混入)。 2026-10-02 真实详情页核对:MediaInfo 只取 #mediainfo-raw 原文(#mediainfo-info 是摘要);豆瓣块去掉标题行与「该信息最后更新」提示。",
|
||||
"umt": {
|
||||
"categoryNames": {
|
||||
"401": "电影",
|
||||
@@ -30,7 +30,9 @@
|
||||
"detail": {
|
||||
"page": {
|
||||
"labelSelectors": ["div.font-bold.leading-6", "span.font-bold"],
|
||||
"fileListPath": "viewfilelist.php?id={id}"
|
||||
"fileListPath": "viewfilelist.php?id={id}",
|
||||
"mediaInfo": "#mediainfo-raw",
|
||||
"descriptionStrip": "div.mt-5, div.flex.flex-row.items-center"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user