# 评论完整度提升方案(签名能力 / 多源交叉) > **状态:方案待评审,尚未实施。** 本文档只做设计与论证,不改动 `tiktok_stats.js`。 > 立项背景:`7552202593888603410` 官方显示评论 **18,900**,tikwm 实得顶级评论 **9,931(52%)**, > 天花板卡在 `cursor ≈ 10369`。计数 4 项(点赞/评论/分享/收藏)已无精度问题,本文只解决**评论覆盖率**。 > 编制日期:2026-09-25 --- ## 一、先把问题问对:那堵墙在哪一层 在讨论"怎么突破"之前,必须先确认 10369 是什么性质。三种假设,对应完全不同的投入: | 假设 | 墙的真实位置 | 突破手段 | 成本 | |---|---|---|---| | **H1** | tikwm 自己的实现上限(硬编码 / 自身会话) | 换源、多源并行 | 极低 | | **H2** | TikTok 对**单个匿名会话**的读取深度限制 | 换 session / 换 ttwid / 换 IP | 中 | | **H3** | 官方接口缺**签名**(X-Bogus + X-Gnarly)被拒 | 自建签名服务 | 高 | ### 关键旁证(已公开可查,非推测) - **H2 成立的证据**:Apify 的 `stanvanrooy6/tiktok-comments-scraper` 在 FAQ 中明确描述 ——「TikTok caps how deep one anonymous session can read; the scraper measures that wall and rotates sessions to keep reading」,并给出 2026 年 9 月的实测:**两个匿名会话收集 25,133 条 唯一评论(1100 万评论量的视频,30 分钟内)**,**单个会话放慢节奏则读过了 37,000 条**。 → 说明「匿名会话深度墙」真实存在,**且可以通过轮换会话穿透**。 - **H3 成立的证据**:TikTok 侧签名已演进为 **X-Bogus + X-Gnarly 双签名**(X-Gnarly 为新增), 且 TikTok 使用 **ttwid + msToken 设备级指纹 + TLS 指纹校验**,纯 Python 客户端被秒级拦截。 - **对 H1 的怀疑**:tikwm 能返回 `total: 18752`,说明它知道总数,却只给到 10369。 这个数字既不等于 18752,也不是整数关口,形态上更像**上游会话的读取深度**或**其自身的软截断**。 > **结论:不先做诊断就投入签名或真机方案,有 50% 以上的概率是在解决一个不存在的问题。** --- ## 二、L0 诊断(半天,零成本,必做第一步) 四个实验,全部可在现有基础设施上完成(云机 + NekoBox 多节点 + 本机),不改主脚本, 用 `_probe/` 下的一次性脚本跑。 ### 实验 0-1:cap 是固定阈值还是随视频变化 取 4 个评论量差异明显的视频(≈500 / 5,000 / 19,000 / 50,000+),各自跑到无数据,记录 cap。 - 若 cap 全部落在 ≈10369 附近 → **固定阈值**(指向 H1 或某个全局参数) - 若 cap 随视频规模成比例浮动 → 另有机制,需重新定位 **这是信息量最大的一个实验。** 一个固定数字意味着可以绕;一个比例意味着要换思路。 ### 实验 0-2:cap 是否与客户端出口 IP 相关 同一视频、同一 cursor 区间,分别用云机节点 A / 节点 B / 本机出口各跑一遍,比较 cap。 - cap 随出口变化 → **墙绑定出站会话** → 换节点/换 session 可推进(直接支持 L1 与 L3) - cap 完全不变 → 与客户端无关,墙在 tikwm 内部或上游 ### 实验 0-3:换镜像源看各自 cap 同一视频分别打 tikwm 与至少一个独立源,记录各自 cap 与**返回条目集合**。 - cap 或集合不同 → **多源并集立竿见影**(L1 直接可行,成本 1~2 天) - 完全一致 → 共享同一上游墙,多源只是浪费钱 ### 实验 0-4:10369 处返回体的形态 抓取 `cursor=10300~10400` 区间的原始响应,逐条看返回体。 | 返回形态 | 含义 | |---|---| | `code:0` + `comments:[]` | 上游确实没给 → 真墙 | | `code:-1` / 错误码 | 是限流,不是墙 → 节流/换节点即可 | | `hasMore:true` 但空 | 与已知的「假 false」同族的边界行为 | **交付物**:一张四行的诊断结论表。**这张表决定后面投 L1 / L2 / L3 中的哪一条。** --- ## 三、方案层级 ### L1|多源交叉补齐(低成本 · 1~2 天 · 仅当 0-3 显示 cap 不同时有效) **思路**:不追求单源完整,用多个来源做并集,以 `cid` 去重。 候选源: | 源 | 接入方式 | 备注 | |---|---|---| | `tikwm` | 已在用 | 免费、无 key、当前主力 | | `evil0ctal/douyin_tiktok_download_api` | 自建 Docker | 开源,实现 X-Bogus + A_Bogus,**需浏览器 cookie** | | tokfluence / captapi / parse.bot | REST + key | 付费,接口干净,有 cursor 分页 | | Apify Actor | 平台调用 | 见 L4 | **必须做的量化**:并集**收敛曲线**——每并入一个新源后,新增唯一条目数。当增量 < 1% 时停止, 这就是实际操作上限。**没有这条曲线,就永远说不清"还差多少"。** **L1 的诚实边界**:如果 L0 显示各源共享同一上游墙,L1 的收益接近 0。**别跳过诊断直接做 L1。** --- ### L2|自建签名服务,直连官方接口(中成本 · 3~7 天 · 对应 H3) **首选基座**:`carcabot/tiktok-signature`(开源、Docker、headless Chromium 注入 TikTok 官方 SDK) ``` POST http://:8080/signature { "url": "https://www.tiktok.com/api/comment/list/?aweme_id=...&cursor=0&count=20" } → { "signed_url": "...&X-Bogus=...&X-Gnarly=...", "x-bogus": "...", "x-gnarly": "...", "device-id": "...", "cookies": "ttwid=...; tt_chain_token=...", "navigator": { "user_agent": "...", "platform": "...", ... } } ``` **为什么用浏览器注入而不是纯算法实现**:签名与浏览器环境(UA / platform / 屏幕尺寸)**强绑定**, 且 TikTok 有 TLS 指纹校验。用 TikTok 自己的 JS 生成签名,等价于"借官方 SDK 签名", 在 schema 更新时**只需重启容器**,而纯 Python 复刻每次更新都要重写算法。 **实施要点**: 1. 部署位置:**云机**(走 NekoBox 出口,IP 与请求目标地区一致)或本机 Docker。 2. **必须使用响应里返回的 `user_agent`**——UA 不匹配签名直接失效(文档明确警告)。 3. 拿到 `signed_url` 后由我们**自己发请求**(`/signature` 模式),便于自己控制节流与重试; 浏览器代发的 `/fetch` 模式只在签名失效时兜底。 4. 容器会自动刷新会话(每 500 次签名或 30 分钟)。 5. 复用现有节流器:把"取签名"也计入令牌桶,避免签名服务成为新的限流点。 **运维代价(必须提前接受)**:TikTok 每 **2~4 个月**更新一次签名 schema, 失效模式是**静默的空结果**(不是硬报错)。需挂一个每天自检的探针(能否取到非空评论首页)。 --- ### L3|云机真机路线(高保真 · 3~5 天 · 利用你的独有资产) 这是本方案里**性价比最高但最被低估**的一条,因为你的环境有别人没有的东西: **root 云机 + 真实 TikTok App + 已登录态 + 可换节点的 NekoBox**。 TikTok 的防线(ttwid 设备指纹、TLS 指纹、msToken 行为序列)**全部是针对"伪造浏览器"设计的**, 而真机+真 App 天然携带全部合法指纹。 #### L3-A|WebView 自动滚动抓包(★ 推荐) 在 Auto.js 中创建 WebView 加载视频页,注入 JS 同时 hook `XMLHttpRequest` 与 `window.fetch`, 捕获 `/api/comment/list/` 的响应体;用注入脚本自动滚动评论区触发分页加载。 - **不是无障碍权限**——WebView 是应用内组件,全程 API 驱动,符合你最初"不用无障碍"的约束 - 复用现有 Auto.js 基础设施与推送流程(`/sdcard/Download/` + isolate 目录) - 签名由 TikTok 自己的 JS 生成,**我们完全不碰算法**,schema 更新对它无感 - 代价:速度受渲染限制(比纯 API 慢),且需要处理滚动到底与懒加载等待 > 这条路线本质是"**用真实浏览器去抓**"。业界结论一致:在 TikTok 上, > 真实 Chrome 会话的拦截率远低于 Playwright/Python 方案——而云机上的真机 WebView 更彻底。 #### L3-B|mitmproxy + Frida 反 SSL pinning 抓 App 的真实评论请求,提取其签名头,在外部重放。 - 优点:能拿到 App 端的完整签名与 ttwid - 代价:需过 SSL pinning,且 App 请求参数与 web 端不同,重放需逐字段对齐 #### L3-C|Frida hook App 网络层 直接调用 App 内部函数让它自己去请求,我们只收结果。 - 保真度最高(连风控评分都继承),但实现与维护成本最高,**不建议首选** --- ### L4|付费现成源(最快 · 当天可用) `stanvanrooy6/tiktok-comments-scraper`(Apify):**$0.40 / 1,000 条**,无需登录、无 cookie。 - 它的实测能力**正好覆盖你的缺口**:单视频 25,133 / 37,000+ 条,远超 9,931 - 10,000 条 ≈ **$4**;这是一次性补全本项目缺口的最低成本 - 代价:数据流向第三方、按量计费、依赖供应商存续 - 适合:**一次性/少量视频**需要高完整度,或用它作为 L1 的"交叉校验源"验证我们的抓取是否有遗漏 --- ## 四、决策矩阵 | 方案 | 成本 | 预期完整度 | 失效风险 | 长期维护 | 数据安全 | |---|---|---|---|---|---| | **L1 多源交叉** | 1~2 天 | 取决 0-3,可能 0% 也可能 80~95% | 低 | 多源各自失效 | 中(触第三方) | | **L2 自建签名** | 3~7 天 | 高(受官方接口深度限制) | **高**(2~4 月一换) | 需常驻运维 | 高(数据不过第三方) | | **L3-A WebView** | 3~5 天 | 高 | **低**(真机真指纹) | 低(算法无感) | 高 | | **L3-B/C Frida** | 7~15 天 | 最高 | 中 | 中 | 高 | | **L4 付费源** | 当天 | 高(供应商已解决) | 低 | 无 | **低**(数据出境) | --- ## 五、推荐路径 ``` L0 诊断(半天,零成本) │ ├─ 0-3 显示各源 cap 不同 ──────► L1 多源交叉(1~2 天,先拿便宜收益) │ ├─ cap 随出口 IP 变化 ─────────► L3-A WebView 为主 + L1 交叉校验 │ ├─ 各源 cap 相同且与 IP 无关 ──► 墙在上游 │ ├─ 少量/一次性 ──► L4(当天,$4 量级) │ └─ 长期大量 ─────► L3-A(3~5 天) │ └─ 官方接口在真机/真签下能深翻 ─► L2 自建签名(3~7 天,接受长期运维) ``` **一句话**:**L0 没做完之前,不要写一行 L2/L3 的代码。** 理由很直接——如果 0-3 发现 cap 是 per-mirror 的,那么 **L1 用 1~2 天就能拿到大部分收益, 而 L2 要 3~7 天并且终身运维**。先在便宜的地方找答案。 **我的推荐倾向**:即使 L0 显示墙在上游,长期方案也**优先 L3-A 而非 L2**。 L2 的签名算法是持续对抗(每 2~4 个月重置一次,且静默失败、难排查), 而 L3-A 让 TikTok 自己的代码去签名——**把维护成本转移给了对手方**。 你手上那台 root 云机 + 真 App 的组合,正是这个路线成立的前提。 --- ## 六、先定义"完整",再谈完整度(重要) 现在说"完整"缺一个可验收的定义。三个必须先澄清的事实: 1. **18,900 是展示值,不是可达值。** 各家的说明一致:显示评论数**包含已删除与已隐藏的评论**, 即使小视频,实际可取行数也略低于显示值。**100% 在数学上就不存在。** 2. **按热度排序的分布极度倾斜。** 前 10,000 条评论承载的互动量通常已占绝大部分。 **如果你的用途是舆情/内容分析,"覆盖前 1 万条"和"覆盖 1.89 万条"的结论差异可能远小于直觉。** 3. **验收应该用收敛曲线,而不是单一数字。** 建议指标: - **并集收敛**:新增源带来的增量 < 1% 时认定为操作上限 - **排名覆盖率**:对比 L4 付费源的结果,量化我们**漏掉了哪些**(是尾部长尾,还是随机分布) **建议先把"最小可接受覆盖率"定下来**(比如 85%)。定完之后,很可能 L1 就够, 不需要 L2/L3 的重投入。**这一步花 10 分钟,可能省下 5 天。** --- ## 七、风险与合规 | 风险 | 说明 | 缓解 | |---|---|---| | 会话农场加剧封禁 | 频繁轮换 session 会被判为扫描器 | 用住宅/移动节点,按信号轮换而非定时 | | L2 静默失效 | schema 更新后返回空结果而非报错 | 每日探针自检 | | L4 数据出境 | 评论含用户名等标识 | 按 GDPR/《个保法》口径评估 | | 条款风险 | TikTok ToS 禁止自动化访问 | 与法律合规性是两个独立问题,需分别评估 | | 单一镜像施压 | tikwm 是免费服务 | 沿用现有节流,多源分摊压力 | --- ## 八、待你决策的事项 1. **是否先执行 L0 诊断?**(建议:是。半天,零成本,且能砍掉一半错误投入) 2. **"最小可接受覆盖率"定多少?**(决定要不要上 L2/L3) 3. **是长期批量还是少量一次性?**(决定 L4 付费源的性价比) 4. **L3-A 是否可接受"速度慢于纯 API"**?(换来的是近乎免疫的稳定性) 回答这 4 个问题,就可以直接进入实施。