feat(adapters): port MoviePilot open site framework (7 spiders, 20 user parsers) + MovieClaw v0.27.0 site definitions + mp-sync tools (W1-3c)

- sites/spiders: Haidan/HDDolby/RousiPro/SunnyPT/TNode/TorrentLeech/Yema (+mTorrent wrapper), specialized SiteAdapter, indirect download resolved at download time
- sites/user-parsers: SiteParserBase + all 20 MP SiteSchema parsers (lxml XPath via xpath+xmldom), refreshSiteUserData with schema fallback
- sites/definitions: zod SiteDefinition schemas, 23 MovieClaw v0.27.0 (MIT) definitions via scripts/mp-sync/movieclaw-import.mjs, registry getSiteDefinition/listSiteDefinitions, NOTICE
- scripts/mp-sync: ledger.json (upstream sha256), check.mjs, build-ledger.mjs; docs/porting/mp-sync-ledger.md
- license-and-provenance: add copied-mit kind, re-anchor MovieClaw rows to v0.27.0

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-09-27 18:39:27 +08:00
1 parent cf85481d95
commit d9f2af2f3c
166 files changed
+16577 -186

No files matched your search

@@ -1,7 +1,16 @@
{
"_provenance": "按 MoviePilot SiteSpider indexer schema 手写;字段结构参考 MovieClaw audiences.yaml(data-ref,未复制);选择器值按 NexusPHP 公开页面惯例编写,仅对 testkit mock 验证,待真实页面核验。见 ../README.md",
"id": "audiences",
"name": "观众",
"enabled": true,
"schema": "NexusAudiences",
"provenance": {
"source": "movieclaw",
"ref": "v0.27.0",
"commit": "c79bb1b0",
"license": "MIT",
"file": "src/movieclaw_tracker/sites/configs/audiences.yaml",
"overrides": "scripts/mp-sync/movieclaw-overrides/audiences.json"
},
"domain": "https://audiences.me/",
"encoding": "UTF-8",
"public": false,
@@ -10,14 +19,45 @@
"result_num": 100,
"timeout": 30,
"search": {
"paths": [{ "path": "torrents.php", "type": "all" }],
"params": { "search": "{keyword}", "search_area": 4 }
"paths": [
{
"path": "torrents.php",
"type": "all"
}
],
"params": {
"search": "{keyword}",
"search_area": 4
}
},
"batch": {
"delimiter": " ",
"space_replace": "_"
},
"browse": {
"path": "torrents.php?page={page}",
"start": 0
},
"batch": { "delimiter": " ", "space_replace": "_" },
"browse": { "path": "torrents.php?page={page}", "start": 0 },
"category": {
"movie": [{ "id": "401", "cat": "Movies", "desc": "电影" }],
"tv": [{ "id": "402", "cat": "TV Series", "desc": "剧集" }, { "id": "403", "cat": "TV Shows", "desc": "综艺" }],
"movie": [
{
"id": "401",
"cat": "Movies",
"desc": "电影"
}
],
"tv": [
{
"id": "402",
"cat": "TV Series",
"desc": "剧集"
},
{
"id": "403",
"cat": "TV Shows",
"desc": "综艺"
}
],
"music": []
},
"torrents": {
@@ -25,28 +65,62 @@
"selector": "table.torrents > tbody > tr:has(table.torrentname), table.torrents > tr:has(table.torrentname)"
},
"fields": {
"title_default": { "selector": "a[href*=\"details.php?id=\"]" },
"title_optional": { "selector": "a[title][href*=\"details.php?id=\"]", "attribute": "title" },
"title_default": {
"selector": "a[href*=\"details.php?id=\"]"
},
"title_optional": {
"selector": "a[title][href*=\"details.php?id=\"]",
"attribute": "title"
},
"title": {
"text": "{% if fields['title_optional'] %}{{ fields['title_optional'] }}{% else %}{{ fields['title_default'] }}{% endif %}"
},
"details": { "selector": "a[href*=\"details.php?id=\"]", "attribute": "href" },
"download": { "selector": "a[href*=\"download.php?id=\"]", "attribute": "href" },
"details": {
"selector": "a[href*=\"details.php?id=\"]",
"attribute": "href"
},
"download": {
"selector": "a[href*=\"download.php?id=\"]",
"attribute": "href"
},
"imdbid": {
"selector": "a[href*=\"imdb.com/title/tt\"]",
"attribute": "href",
"filters": [{ "name": "re_search", "args": ["tt\\d+", 0] }]
"filters": [
{
"name": "re_search",
"args": ["tt\\d+", 0]
}
]
},
"date_elapsed": {
"selector": "td:nth-child(4) > span"
},
"date_added": {
"selector": "td:nth-child(4) > span",
"attribute": "title"
},
"date_elapsed": { "selector": "td:nth-child(4) > span" },
"date_added": { "selector": "td:nth-child(4) > span", "attribute": "title" },
"date": {
"text": "{% if fields['date_elapsed'] or fields['date_added'] %}{{ fields['date_added'] if fields['date_added'] else fields['date_elapsed'] }}{% else %}now{% endif %}",
"filters": [{ "name": "dateparse", "args": "%Y-%m-%d %H:%M:%S" }]
"filters": [
{
"name": "dateparse",
"args": "%Y-%m-%d %H:%M:%S"
}
]
},
"size": {
"selector": "td:nth-child(5)"
},
"seeders": {
"selector": "td:nth-child(6)"
},
"leechers": {
"selector": "td:nth-child(7)"
},
"grabs": {
"selector": "td:nth-child(8)"
},
"size": { "selector": "td:nth-child(5)" },
"seeders": { "selector": "td:nth-child(6)" },
"leechers": { "selector": "td:nth-child(7)" },
"grabs": { "selector": "td:nth-child(8)" },
"downloadvolumefactor": {
"case": {
"img.pro_free": 0,
@@ -65,17 +139,31 @@
"*": 1
}
},
"freedate": {
"selector": "img[class^=\"pro_\"]",
"attribute": "title",
"filters": [{ "name": "re_search", "args": ["\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}", 0] }]
"description": {
"selector": "span.torrent-subtitle-line"
},
"description": { "selector": "span.torrent-subtitle-line" },
"labels": { "selector": "span.tags" },
"category": {
"selector": "a[href*=\"?cat=\"]",
"attribute": "href",
"filters": [{ "name": "querystring", "args": "cat" }]
"filters": [
{
"name": "querystring",
"args": "cat"
}
]
},
"freedate": {
"selector": "img[class^=\"pro_\"]",
"attribute": "title",
"filters": [
{
"name": "re_search",
"args": ["\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}", 0]
}
]
},
"labels": {
"selector": "span.tags"
}
}
},
@@ -84,14 +172,47 @@
"kind": "nexusphp",
"displayName": "观众",
"timezone": "+08:00",
"rateLimit": { "minIntervalMs": 3000, "burst": 1 },
"capabilities": { "list": true, "search": true, "detail": true, "download": true, "rss": true },
"categoryNames": { "401": "电影", "402": "剧集", "403": "综艺", "406": "纪录片" },
"rateLimit": {
"minIntervalMs": 3000,
"burst": 1
},
"capabilities": {
"list": true,
"search": true,
"detail": true,
"download": true,
"rss": true
},
"categoryNames": {
"401": "电影",
"402": "剧集",
"403": "综艺",
"406": "纪录片"
},
"loginSuccess": "a[href*=\"logout\"]",
"emptyMarkers": ["没有种子", "没有结果", "Nothing found"],
"pagination": "a[href*=\"page=\"]",
"detailPath": "details.php",
"downloadPath": "download.php",
"login": {
"path": "login.php",
"usernameField": "username",
"passwordField": "password",
"errorCss": "td.text"
},
"profile": {
"path": "userdetails.php",
"uid_css": "a[href*='userdetails.php?id=']::attr(href)",
"username_css": "a[href*='userdetails.php?id=']",
"class_css": "td.rowhead:contains('等级') + td::text",
"uploaded_css": "span.site-userbar__compact-metric--uploaded",
"downloaded_css": "span.site-userbar__compact-metric--downloaded",
"ratio_css": "td.rowhead:contains('分享率') + td::text",
"bonus_css": "td.rowhead:contains('魔力') + td::text",
"join_date_css": "td.rowhead:contains('加入日期') + td::text",
"seeding_css": "td.rowhead:contains('当前做种') + td::text",
"leeching_css": "td.rowhead:contains('当前下载') + td::text"
},
"detail": {
"path": "details.php",
"title": "h1#top",