# REQ · ID提取 需求重整 v2(**已实施** · v8 三段式落地) > ✅ **状态:已实施**。本文就是 v8 那次改造的依据(删 5 / 合并 7 / 改名 6 / 置灰 3 / 保留 17 > 与三段式结构都已落地)。保留作需求原始记录。 > 对象:`tiktok-app` 界面「任务 › ID提取」的四张脚本卡 + 功能设置。 > 目标:不再往上加功能,而是**把已经存在但互相矛盾的需求理清**,让每个控件都有唯一、可执行的语义。 > 依据:`《实施规格书_飞舟脚本_2026-10-13》`(资料库 `JZf9xTgLXBFgjXJ4dJWVsU`)+ 现有代码实测。 > 配套:`PLAN_id_extract.md`(执行功能方案)。本文只谈**要什么**,不谈怎么实现。 --- ## 0. 摘要 **乱不在控件多少,在于每个控件没有唯一的行为定义。** 实测:ID提取共 **38 个业务字段**(+4 个 `checked` +4 个 `expanded`)。其中 **10 个是"纯开关"** —— 勾上之后旁边没有任何输入或选择,**执行时无从下手**;而其中 **4 个与它所在的卡片同名** ("自定关注或粉丝页面提 ID"、"自定评论页面提 ID"、"文本 UID 裂变提 ID"、"关键词视频提 ID"), 等于"勾了这张卡之后再确认一次要不要用这张卡"。 四张卡也不是四个功能,而是「**起点**(人从哪来)」×「**深度**(要不要再展开一层)」 的 4 个**不完整组合**。于是同一批人能用不同卡抓到,用户不知道该选哪个; 而想同时要两种来源时,**单选约束又不允许**——这条约束本身就是分类错了的信号。 --- ## 1. 乱在哪:10 条具体问题 每条都给证据,不是感觉。 ### 1.1 四个开关与卡片同义反复(4 处) | 卡片 | 卡内第一个开关 | 问题 | |---|---|---| | 脚本一 · 粉丝页提 ID | 「自定关注或粉丝页面提 ID」默认 ✓ | 和卡名重复 | | 脚本二 · 评论页提 ID | 「自定评论页面提 ID」默认 ✓ | 和卡名重复 | | 脚本三 · 文本 UID 裂变提 ID | 「文本 UID 裂变提 ID」默认 ✗(代码 true) | 与卡名**一字不差** | | 脚本四 · 关键词视频提 ID | 「关键词视频提 ID」默认 ✗(代码 true) | 与卡名**一字不差** | **后果**:用户已经通过单选圆点选了这张卡,再看一个"要不要启用"的开关,只能猜: 关掉它是不是等于不选这张卡?如果等于,为什么不直接取消勾选?如果不等于,那它到底关掉了什么? **执行侧也无法回答这个问题** —— 这正是语义缺失的直接体现。 ### 1.2 脚本一把三种互斥起点塞进一张卡(最严重的结构问题) 脚本一里同时存在三条取材路径,靠 2 个开关区分,**且没有定义"三个都开"或"都不开"的行为**: | 控件 | 隐含的起点 | |---|---| | 主播 ID(输入框)+ 进入页面(下拉) | 指定账号主页 | | 自定页面提 ID(纯开关) | 搜索结果里的用户 | | 使用文本 ID(开关 + 路径) | 文本文件里的 UID | 其中「自定页面提 ID」**勾上后没有任何输入**(`page-id.js:126` 只有 `W.checkRow`,无右侧控件) —— 自定义**哪个**页面?执行时从哪开始?无解。 而「使用文本 ID」做的事与脚本三的「裂变文本」**是同一件事**(两者默认路径完全相同,都是 `/sdcard/Download/tiktok_app/uid_list.txt`)。 ### 1.3 10 个纯开关,勾上之后无所指 勾选后**既没有输入、也没有选择**,因此无法确定执行行为: | 卡片 | 纯开关 | |---|---| | s1 | 自定关注或粉丝页面提 ID、自定页面提 ID | | s2 | 自定评论页面提 ID、提取评论的人的粉丝 ID | | s3 | 文本 UID 裂变提 ID、UID 博主去重 | | s4 | 关键词视频提 ID、关键词提取主播粉丝 ID、关键词提取评论区 ID、关键词提取评论的人的粉丝 ID | 只有 s1 的「主播去重」是"开关 + 右侧下拉"的完整形态(`buildToggleRow` 的 `rightOf`)。 **同一个项目里两种开关形态并存,用户无法从外观判断哪个开关后面还有东西。** ### 1.4 同名不同义:「进入页面」在两张卡里指两件事 | 位置 | 候选值 | 实际含义 | |---|---|---| | s1 `enterPage` | 粉丝页 / 评论页 / 主页 / 关注页 | "去哪个页面取材" | | s3 `enterPage` | 同上(默认关注页) | "对文本里的 uid **展开哪个列表**" | 同一个下拉名、同一套候选值、**两套语义**。用户在 s3 看到"进入页面=关注页", 会以为脚本要"进入某个关注页",实际是"取这些 uid 的关注列表"。 ### 1.5 去重散落三处,且没人知道它们的关系 | 位置 | 控件 | 管什么? | |---|---|---| | s1 | 主播去重(开关)+ 去重模式(ID 模式/文本模式) | 主播?全部 ID? | | s3 | UID 博主去重(纯开关) | 与上面是同一个东西吗? | | 功能设置 | 云端去重(开关)+ 表名 + 连通测试 | 本地与云端是并存还是互斥? | 三处描述同一件事的不同侧面,分布在不同卡片与不同区域。**"主播去重"这个词尤其含糊** —— 产物是 ID,不是主播;到底去重对象是"取材起点"还是"输出的每一个 ID"? ### 1.6 「裂变」这个词承担了三个未定义的语义 脚本三的卡名与开关都叫"文本 UID 裂变",但"裂变"至少可以指: ① 文本里的 uid → 取这些人的粉丝/关注(一层展开); ② 文本里是关键词 → 搜人 → 再展开; ③ 文本里的 uid → 直接产出(不展开)。 **三种实现的工作量差几倍,而界面完全一样。** ### 1.7 脚本四四个开关是"层层嵌套",却排成四个平级项 文案都以「关键词」开头、长度接近、控件形态相同: ``` 关键词视频提 ID ✗ 关键词提取主播粉丝 ID ✗ 关键词提取评论区 ID ✗ 关键词提取评论的人的粉丝 ID ✗ ``` 实际关系是:**视频来源 → 作者 → 作者的粉丝 / 评论区 / 评论者的粉丝**(第 1 个是根, 后 3 个是并列的可选扩展)。排成四项平级,用户读不出"1 是根,2/3/4 是扩展", 更读不出"2 和 3 是同一层,4 是更深一层"。 ### 1.8 功能设置的 14 项,混了三种性质的东西 | 性质 | 项 | 问题 | |---|---|---| | 过滤条件(会丢人) | 私密、无头像、语言、区域、四组数量门槛 | 与"检测"混在一起 | | 检测方式(决定怎么判) | 昵称个签检测(通杀/仅昵称/仅个签) | 它是前者的**取样字段**,不是独立设置 | | 需要外部能力的开关 | 云端去重、AI 头像识别、AI 性别、AI 年龄 | 当前都没有承载者,却能打开 | 「提取区域」的说明文案更直接暴露问题:弹窗写**"勾选后,只提取符合上方国家简码的账号"** (`page-id.js:362`),但这一行**根本没有勾选框**,上面是一个输入框。 ### 1.9 默认值与规格书不一致(2 处) | 字段 | 规格书 C3 | 代码 | |---|---|---| | s3 `uidFission` | ✗ | `true` | | s4 `keywordEnabled` | ✗ | `true` | 代码里这么写是**有理由的**(都设 ✗ 的话,脚本三/四展开后整片是关的,用户会以为坏了), 但这恰好说明:**这些开关本身就不该存在** —— 一个"默认必须打开、否则页面看起来是坏的"的开关, 是没有信息量的。 ### 1.10 单选约束与用户的真实意图冲突 规格书写「单选:同一时间仅可运行一个脚本」。但用户的真实需求常常是组合的: "先抓关键词视频的作者,再把文本里这批 uid 的粉丝也抓一遍"。 当前结构下**做不到**,只能分两次运行、两次产出去手动合并。 --- ## 2. 病根(两条,改界面之前必须先认) ### 2.1 需求只描述了"控件长什么样",没描述"执行时意味着什么" 规格书是从画布反推出的**字段表**:它准确记录了"这一行有一个复选框、默认 ✓", 但没有记录"勾上之后,脚本要做什么、不勾要做什么、和别的开关同时勾时听谁的"。 这就是为什么做执行方案时**被迫猜了三处语义**(主播 ID 留空 / `customFansPage` / 裂变)。 **"界面乱"和"执行要猜"是同一个病**。所以本次重整的主产出不是排版, 而是给每个控件补上**唯一的行为定义**。 ### 2.2 分类维度不唯一:四张卡是「起点 × 深度」的不完整组合 真正的两个维度是: - **起点**(人从哪来):指定账号 / 搜索结果 / 某个视频的评论区 / 文本文件 / 当前屏幕 - **深度**(要不要再走一层):只要这个人 / 再取他的粉丝·关注 把四张卡拆到这两个维度上: | 旧卡 | 起点 | 深度 | 它缺的能力(被塞在别处了) | |---|---|---|---| | s1 粉丝页 | 指定账号主页 | 1 层(列表) | 缺"搜索用户"(塞在 s1 自己的 `customPage`)、缺"文本"(塞在 `useTextId`) | | s2 评论页 | 某视频评论区 | 0~1 层 | **缺"视频从哪来"** —— 只有"自定评论页面"= 假定用户已停在评论区 | | s3 文本 | 文本文件 | 1 层 | 缺"直接用文本里的 uid"(不展开) | | s4 关键词视频 | 搜索视频 | 0~2 层(3 种扩展) | 缺"搜索用户"起点 | 四张卡各缺一块、各有别人没有的一块,**合起来才完整**。 所以"选一个脚本"这个动作本身就是在**替用户做减法**,而用户往往不想减。 --- ## 3. 新需求:三段式 任何"ID 提取"工具都只有三步。把结构改成这三步,四个脚本自然消失。 ``` ① 取材 从哪儿找人 → 可累加的取材清单(1 条或多条,串行执行) ② 过滤 只要什么样的人 → 一组共用条件(所有取材都适用) ③ 输出 要多少、存哪 → 上限 + 去重 + 文件 ``` ### 3.1 取材:5 种起点 + 1 个深度选项 用户只需回答两件事:**从哪开始**、**要不要再往下走一层**。 | # | 起点 | 用户要提供 | 能取到 | 能否再展开一层 | |---|---|---|---|---| | A | **指定账号** | 账号(多个用 `#` 分隔) | 粉丝列表 / 关注列表 / 主页展示的账号 | ✅ 展开后可再取粉丝/关注 | | B | **搜索结果** | 类型(用户 / 视频)+ 关键词 | 用户搜索结果里的人 / 视频的作者 | ✅ 同上 | | C | **某个视频的评论区** | 视频从哪来(当前屏幕 / 关键词搜到的) | 评论者 | ✅ 取评论者的粉丝 | | D | **文本文件** | 文件路径 | 文件里的每一行 uid | ✅ 取这些人的粉丝/关注 | | E | **当前屏幕** | 无 | 屏幕上这个列表里的人 | ❌ 已是最底 | **规则(必须写进需求,否则又会含糊)**: 1. **一条取材 = 一个起点 + 它需要的输入 + 它的深度选项**。选了起点才出现该起点的输入, 不会再有"勾上却无所指"的开关。 2. **取材可以有多条,按顺序串行执行**(同一台手机只有一个前台,没有并发可言)。 多条之间共用同一份去重集合与同一个输出文件。 3. **深度最多 2 层**(列表里的人 → 这些人的粉丝)。 原因:100 个粉丝 × 每人 100 粉丝 = 1 万次用户页打开,在真机上不现实,也会让账号看起来异常。 第 3 层直接不给选项。 4. **每条取材至少要有 1 个可执行输入**,否则这条不予启动(启动前拦住并指出是哪一条缺什么)。 ### 3.2 旧四张卡 → 新取材的三条常用配置(等价物) 改结构不等于丢掉用户熟悉的用法。三个常见场景在新结构下的写法: | 用户想干的 | 旧操作 | 新操作 | |---|---|---| | 抓某个主播的粉丝 | 脚本一(默认就是) | 一条取材:指定账号 `xxx` → 取「粉丝列表」 | | 抓关键词视频的作者的粉丝 | 脚本四 | 一条取材:搜索结果「视频 + 关键词」→ 取「作者」→ 深度「作者粉丝」 | | 把文本里这批 uid 的粉丝抓一遍 | 脚本三 | 一条取材:文本文件 → 深度「这些人的粉丝」 | **并且多了一个旧结构做不到的能力**:以上三条可以**同时**配(三条取材串行跑,共用一个输出)。 ### 3.3 过滤:从 14 项收敛成 2 组,逐项写明执行语义 **A 组 · 只要这样的账号** | 项 | 执行语义(必须唯一) | 现状定性 | |---|---|---| | 过滤私密账户 | 读不到"私密"提示 → 保留;读到 → 丢 | 可做 | | 过滤无头像账户 | 头像是默认占位图 → 丢 | 可做(需像素判定) | | 语言 | 取**昵称 + 个签**的字符组成:中文占比 ≥ 阈值 → 中文;拉丁 ≥ 阈值 → 英文;都不满足 → 丢 | 可做(纯本地) | | 昵称个签检测 | **不是一个过滤条件,是上面"语言"的取样范围**:通杀 / 只看昵称 / 只看个签 | 需改名并归到"语言"下面 | | 提取区域 | TikTok 用户页**不显示国家**,无可用的判定数据源 | **标「暂不支持」**,不给可开的开关 | | AI 头像识别 / AI 性别 / AI 年龄 | 需要模型,本期无承载者 | **标「暂不支持」** | **B 组 · 数值门槛** | 项 | 执行语义 | |---|---| | 关注量 / 粉丝量 / 获赞量 / 视频量(各 min~max) | 读用户页数字(`1.2M` / `12.3K` / `1.2万` 都要能解析)→ 落在区间内才保留 | **C 组 · 去重与输出**(从脚本卡里全部收上来,只出现一次) | 项 | 执行语义 | |---|---| | 本地去重 | 与"历史已提取"(跨轮)+ "本次已收"(同轮)比对,重复的跳过。**默认开** | | 云端去重 | 未配置服务地址时不生效,并在日志里明说「本次仅本地去重」,**不静默** | | 提取上限 | 凑满 N 个即结束。`0` = 不限,但受引擎的物理护栏约束(最大时长 / 最大翻屏数),到护栏时**如实说明** | **关键规则**:**"暂不支持"的项必须是灰的并带一个 ⓘ 说明原因**,不能给一个能打开、 打开后什么也不发生的开关。现在的「云端去重」就是这样:开关能开,但"连通测试"只会告诉你 "当前未配置服务地址"。 ### 3.4 界面结构(新) ``` ┌─ ID提取 ────────────────────────────────────┐ │ │ │ ① 取材 │ │ 说明:可添加多条,按顺序执行;共用同一份去重与输出 │ │ │ │ ┌ 第 1 条 ─────────────────────────────┐ │ │ │ 起点 [指定账号 ▾] │ │ │ │ 账号 [ID1#ID2#ID3 ] │ │ │ │ 取 ☑ 粉丝列表 ☑ 关注列表 ☐ 主页展示 │ │ │ │ 深度 ☐ 再取这些人的粉丝(最多 2 层) │ │ │ └──────────────────────────────────────┘ │ │ ┌ 第 2 条 ─────────────────────────────┐ │ │ │ 起点 [文本文件 ▾] │ │ │ │ 文件 [/sdcard/Download/tiktok_app/uid_list.txt] [选择] │ │ │ 深度 ☑ 再取这些人的粉丝 │ │ │ └──────────────────────────────────────┘ │ │ [+ 添加一条取材] │ │ │ │ ② 只要这样的账号 │ │ ☑ 过滤私密 ☑ 过滤无头像 │ │ 语言 [通杀 ▾] 取样 [昵称+个签 ▾] │ │ 区域 [暂不支持 ⓘ] │ │ 关注量 [0]~[500000] 粉丝量 [0]~[500000] │ │ 获赞量 [0]~[500000] 视频量 [0]~[500000] │ │ │ │ ③ 输出 │ │ 提取满 [0=不限] 个后停止 │ │ 去重 ☑ 本地 ☐ 云端(需先在「我的」配置服务) │ │ 文件:uid_20261017_1100.txt(自动命名) │ └──────────────────────────────────────────────┘ ``` **与旧页面相比去掉的东西**(都是本次诊断出来的问题源): | 去掉 | 原因 | |---|---| | 四张"脚本"卡 + 单选圆点 | 起点与深度是两个维度,不该做成 4 个互斥选项(§2.2) | | 「单选:同一时间仅可运行一个脚本」说明 | 约束随结构消失:取材是串行清单,本来就只有一个在跑 | | 4 个同义反复的开关 | §1.1 | | 6 个"勾上却无所指"的纯开关 | §1.3 —— 全部变成"选了起点才出现的输入" | | 脚本卡里的三个去重控件 | 收到 ③ 只出现一次(§1.5) | | 「↓ 下方还有功能设置」滚动指引 | 页面从"4 卡 + 长设置"变成三段,一屏半就能看完 | | 「当前脚本:xxx」提示条 | 没有"当前脚本"这个概念了 | ### 3.5 三个必须回答的行为定义(旧需求完全没写) 这三条是本次重整**最实质的产出**,不是排版能替代的: 1. **一条取材跑完、列表翻到底了怎么办?** → 换下一条取材,**不算失败**。 全部取材都跑完才结束,终态是「已完成」。 2. **深度展开的人要不要也过一遍过滤?** → **要**。过滤对所有被收录的 ID 一视同仁 (否则"粉丝的粉丝"会绕过 14 项条件混进产物,这是最容易被忽略的一处)。 3. **同一个 ID 在两条取材里都出现了怎么办?** → 后出现的那次跳过,且**不占用上限名额** (否则用户设了 100 个上限,实际只拿到 60 个新的)。 --- ## 4. 逐字段处置表(38 个业务字段,一个不落) | # | 旧路径 | 处置 | 新归属 | |---|---|---|---| | 1 | s1.customFansPage | **删** | 被「起点=指定账号 + 取哪个列表」取代 | | 2 | s1.customPage | **删** | 它是"起点=搜索结果·用户",独立成一条取材 | | 3 | s1.dedupeEnabled | **移** | ③ 输出 · 本地去重 | | 4 | s1.dedupe | **移 + 简化** | 与 UID 博主去重合并;"ID 模式/文本模式"的差别只是集合来源,不必单独让用户选 | | 5 | s1.enterPage | **改名 + 收窄** | ① 取材 · 「取哪些列表」(多选:粉丝/关注/主页展示),只在起点=指定账号时出现 | | 6 | s1.anchorIds | **保留 + 改名** | ① 取材 · 「账号」 | | 7 | s1.useTextId | **删(合并)** | 选「文本文件」这个起点即等于要用文本,不需要再确认一次 | | 8 | s1.textIdPath | **保留 + 改名** | ① 取材 · 「文件」(与 s3 是同一个概念,只留一份) | | 9 | s2.customCommentPage | **删** | 起点=评论区的输入改为「视频从哪来」 | | 10 | s2.commenterFans | **合并** | ① 取材 · 深度「再取这些人的粉丝」 | | 11 | s3.uidFission | **删** | 同义反复(§1.1) | | 12 | s3.uidDedupe | **删(合并)** | 统一去重 | | 13 | s3.enterPage | **改名** | ① 取材 · 深度里的「展开哪个列表」(粉丝/关注)—— 与 #5 分名,避免同名不同义 | | 14 | s3.fissionTextPath | **合并** | 与 #8 合并为同一个「文件」 | | 15 | s4.keywordEnabled | **删** | 同义反复 | | 16 | s4.keyword | **保留 + 改名** | ① 取材 · 「关键词」 | | 17 | s4.anchorFans | **合并** | ① 取材 · 深度里的「作者粉丝」 | | 18 | s4.commentArea | **保留** | ① 取材 · 与「作者粉丝」并列的一个取材范围 | | 19 | s4.commenterFans | **合并** | ① 取材 · 深度的第 2 层「评论者的粉丝」 | | 20 | features.filterPrivate | 保留 | ② 只要这样的账号 | | 21 | features.filterNoAvatar | 保留 | ② | | 22 | features.regionCodes | **保留但置灰** | ② · 标「暂不支持」+ ⓘ 说明原因 | | 23 | features.langRegion | 保留 | ② | | 24 | features.nicknameCheck | **改名 + 归属** | ② · 「取样范围」(通杀/昵称/个签),挂在语言下面 | | 25 | features.cloudDedupe | 保留 | ③ 去重 | | 26 | features.cloudTable | 保留 | ③ 去重(选云端后才出现) | | 27 | features.aiAvatar | **保留但置灰** | ② · 标「暂不支持」 | | 28 | features.aiGender | **保留但置灰** | ②(依赖 #27) | | 29 | features.aiAgeMax | **保留但置灰** | ②(依赖 #27) | | 30-37 | features.{follow,fans,likes,videos}{Min,Max} | 保留 | ② 数值门槛(8 个,一行一个区间) | | 38 | features.extractLimit | 保留 | ③ 输出 | **统计**:删 5、合并 7、改名 6、置灰 3、原样保留 17(= 38)。 **没有一个字段是"想不出来才删的"** —— 每一条删/合并都对应 §1 里的一个具体问题。 --- ## 5. 两档落地 ### A 档 · 只清语义,不动结构(保守) 保留四张卡、单选、功能设置卡。做 6 件事: 1. 删掉 4 个同义反复的开关(§1.1)→ 直接消除"关掉它等于不选这张卡"的疑问 2. 6 个"纯开关"逐个补上它缺的输入/选择,或改成"选了才出现的行"(§1.3) 3. 两张卡的 `enterPage` 分名:s1「取哪些列表」、s3「展开哪个列表」(§1.4) 4. 三个去重控件收到功能设置,只出现一次(§1.5) 5. 功能设置按 A/B/C 三组重排;3 项置灰标「暂不支持」;改掉「提取区域」那句与控件不符的说明(§1.8) 6. 修 s3/s4 的默认值(§1.9) - **优点**:改动局限在 `page-id.js` + `store.js` 的文案与少量字段;配置迁移小;与规格书差距小。 - **缺点**:**§1.2(s1 塞了三个起点)、§1.10(不能组合)依然存在**。 用户仍然要面对"四选一",而脚本一仍然是个"万能卡"。 ### B 档 · 改成三段式(推荐) 按 §3 重做页面结构:取材清单 + 过滤 + 输出。 - **优点**:一次性解决 §1.1–1.10 全部十条。多了一个真实能力:多种取材组合成一轮运行。 - **缺点**:① 与规格书 C1–C5 的画板结构偏离较大(**需要你明确授权偏离**); ② 取材是**不定长列表**,`Store.FIELDS` 那套"一项一控件"的标量表放不下, 要新建一个 `Sources` 模块(照 `Records` 的先例:另一个 storage key,不塞进字段表); ③ 要做 v6 → v7 迁移(把四张卡的 `checked` 翻译成"一条取材",我已有完整的映射方案)。 ### 推荐:**先 A 后 B**,但只把 A 当作过渡 A 档的 6 件事里有 4 件是 B 档的前置工作(删同义开关、补纯开关的输入、去重收口、置灰标注), 做了不浪费。**但如果只能做一档,选 B** —— A 档做完,用户最不满的那条("想同时抓两种来源") 仍然无解。 --- ## 6. 迁移(仅 B 档需要,v6 → v7) 现有用户配置按"当时勾的是哪张卡"翻译成一条取材,**一个字段都不丢**: | 旧状态 | 新配置 | |---|---| | s1 选中 | 取材 #1:起点=指定账号,账号=`anchorIds`,取=`enterPage` 对应的列表 | | s1 选中 且 `useTextId=true` | 取材 #1:起点=文本文件,文件=`textIdPath` | | s1 选中 且 `customPage=true` | 取材 #1:起点=搜索结果·用户(关键词留空,启动时要求补) | | s2 选中 | 取材 #1:起点=评论区,视频来源=当前屏幕 | | s3 选中 | 取材 #1:起点=文本文件,文件=`fissionTextPath`,深度=`enterPage` | | s4 选中 | 取材 #1:起点=搜索结果·视频,关键词=`keyword`;深度按三个开关逐项映射 | | `dedupeEnabled` / `uidDedupe` / 云端三项 | 统一映射到 ③ 的去重 | | 四张卡都未选 | 取材清单为空 → 启动时拦住「请先添加一条取材」(与现在的 F1 弹窗同形) | 迁移必须**幂等**(跑两次结果一样)且**可回退**(旧字段保留不删,只做读取时翻译)。 --- ## 7. 待拍板 1. **走 A 档还是 B 档?**(推荐 B;A 只当过渡) 2. **允许偏离规格书 C1–C5 的画板结构吗?** —— B 档必然偏离。 规格书是"可执行规格",但它记录的是**控件**,没记录**行为**;本次重整的价值恰在行为。 3. **"暂不支持"的 4 项(区域 + AI 三项)**:置灰保留(推荐),还是从界面删掉? 置灰+ⓘ 的好处是用户知道"以后会有",坏处是界面仍有一行用不了的东西。 4. **深度最多 2 层**这个限制接受吗?(推荐接受,理由在 §3.1) 5. **取材条数上限**给几条?(我建议 5 条,够覆盖全部组合,也不至于让页面长到滚不完) --- ## 8. 与 `PLAN_id_extract.md`(执行方案)的关系 两份文档是**互相印证**的,不是重复: - 执行方案里把四个脚本抽象成 **6 种取材源**,是因为**只能那样**才能写出可执行的流程; - 本文反过来证明:执行层不得不做的抽象,正好说明**界面的分类维度错了**。 - 执行方案里"被迫猜的三处语义"(主播 ID 留空 / `customFansPage` / 裂变), 在本文 §3 里全部变成明确的行为定义 —— **两处文档要么一起改,要么一起不改**。 **若采纳 B 档,执行方案的哪些结论会变**: | 执行方案里的内容 | B 档下是否需要改 | |---|---| | 6 种取材源抽象 | **不变**,它已经是三段式的直接映射 | | `engine-config.json` 的 `id.source` 单对象 | **要改**:变成 `id.sources` 数组 | | 14 项功能设置的分级(A/B/C) | **不变** | | 产物与去重(`uid_*.txt` + `uid_extracted.txt`) | **不变** | | 分阶段实施 P0–P5 | **不变**,但 P3 的"只做脚本一"改为"只做一条取材(指定账号)" | | 界面侧 6 处改动 | **要改**:`buildIdConfig` 从读 4 张卡变成读取材清单 | --- ## 附:一页对照 ``` 旧(四张卡 × 互斥) 新(三段式 × 可累加) ───────────────────────── ───────────────────────── 脚本一 · 粉丝页提 ID ┐ ├ 自定关注或粉丝页面 ✓ │ ① 取材(可多条,串行) ├ 自定页面 ✗ │ 起点[指定账号] 账号[__] 取☑粉丝☑关注 ├ 主播去重 ✓ + 模式 │ 起点[文本文件] 文件[__] 深度☑粉丝 ├ 进入页面=粉丝页 │ 起点[搜索视频] 关键词[__] 深度☑作者☑评论区 ├ 主播 ID [__] │ └ 使用文本 ID ✗ + 路径 ┘ ② 只要这样的账号 脚本二 · 评论页提 ID ☑私密 ☑无头像 语言[通杀] 取样[昵称+个签] ├ 自定评论页面 ✓ ┐ 区域[暂不支持ⓘ] └ 提取评论的人的粉丝 ✗ │ 关注量[0]~[500000] 粉丝量[0]~[500000] 脚本三 · 文本 UID 裂变 │ 获赞量[0]~[500000] 视频量[0]~[500000] ├ 文本 UID 裂变提 ID ✗ │ ├ UID 博主去重 ✓ │ ③ 输出 ├ 进入页面=关注页 │ 提取满[0]个后停止 └ 裂变文本 [__] │ 去重 ☑本地 ☐云端 脚本四 · 关键词视频 │ 文件 uid_20261017_1100.txt(自动) ├ 关键词视频提 ID ✗ │ ├ 关键词主播 [fashion] │ ← 10 个纯开关 → 0 个 ├ 关键词提取主播粉丝 ✗ │ ← 3 处去重 → 1 处 ├ 关键词提取评论区 ✗ │ ← 2 个同名不同义的"进入页面" → 各自分名 └ 关键词提取评论的人的粉丝 ✗ ┘ ← 单选约束 → 消失(本来就该串行) ───────────────────────── 功能设置 14 项(混了过滤/检测/待支持三种性质) ```