# vidcmt 给在线影视(`video_info` 里 `newsType=SP` 的长视频)铺机器人评论,并按后端自己的 口径重算 `commentCount` / `fakeCommentCount`。一次性运营工具,不进 cron。 `scripts/dramacmt` 是同一件事的短剧版,两边的坑大部分重合,差异见下。 ## 为什么不是统一 20~50 条 影视和短剧差两个数量级,而且**真实评论区本来就很稀**。线上 tangguo 实测: | | | |---|---| | 在线影视(`newsType=SP, status=1`) | 105,671 个 | | 其中有可见一级评论的 | 4,437 个 | | 真实可见影视评论总量 | 79,028 条 | | 有评论的对象里只有 1 条的 | 9,291 个 | 照短剧那样每个视频 20~50 条,就是 ~310 万条 `comment` 文档(集合原本一共 35 万条),而且长尾视频评论数比播放量还多,一眼假。 所以按播放量(`fakePlayCount`)分层,让评论数和热度正相关: | 播放量 | 每个视频 | tangguo 实际 | |---|---|---| | ≥ 200,000 | 20~50 条 | ~61 个视频 | | 50,000 ~ 200,000 | 8~20 条 | ~890 个 | | 10,000 ~ 50,000 | 3~8 条 | ~13,300 个 | | 1,000 ~ 10,000 | 1~3 条 | ~58,000 个 | | < 1,000 | 1 条 | ~29,100 个 | 合计 ~23 万条,分层表在 `main.go` 的 `tiers`。 ## 两个计数字段 影视的评论数和短剧不是一套机制: - 评论列表第 1 页的「总条数」是**实时查**的(`commentser.GetTotalComments`), 不读计数器——和短剧第 1 页直接读 `media.countComment` 不同 - 卡片、搜索结果、「最多评论」榜用的是 **`fakeCommentCount`** (`app/service/searcher/video.go:203`、`vidmod.VIDListSortByFakeCommentCount`) - 真实发评论走 `vidmod.IncCommentCount`,两个字段一起 `$inc` (`models/v/vidmod/vid.go:1996`) 本工具铺评论时同样两个字段一起 `$inc`,跑完再做一趟重算,口径取自后端自己的 修复函数 `web/service/commentser.rebuildSingleObjCommentCount` 的 video 分支: ``` count = count({objType:"video", objID, status:1, isAdvertiser:false, isDelete:false}) fakeDelta = max(0, fakeCommentCount - commentCount) // 保留运营手动加的假量 commentCount = count fakeCommentCount = count + fakeDelta ``` 用后端的口径而不是列表的口径,是为了后台万一触发那条重算不会把数字改回去; 影视上两者没有差别——线上 `objType=video` 的评论没有一条缺 `isAdvertiser` 字段。 重算同时修掉两类历史脏数据: - **`fakeCommentCount` 为负数**:`web/vidhelp/redis.go:87` 删评论时 `--`, 减穿了。线上实测 3,966 个在线影视的卡片显示负数评论数 - **有计数没评论**:36,549 个在线影视 `commentCount>0`,但只有 4,437 个真有 可见评论——剩下的是克隆库带过来的、或评论被硬删了 ## 和 dramacmt 的字段差异 抽样线上真实影视评论对出来的,三处和短剧不一样: | 字段 | 影视 | 短剧 | |---|---|---| | `publisherID` | **视频的 `publisherID`** | 0 | | `title` | 留空 | 剧名 | | `city` | **`"-"`** | (dramacmt 写了真城市) | `city` 这条要特别注意:发评论路径里 `GetLocationByIP` 的调用是**注释掉的** (`app/service/commentser/cmtsend.go:114-116`),所以线上 79,063 条可见影视评论 **全部**是 `"-"`,真实短剧评论也是。`City` 会原样出参给 App (`cmtcoverter.go:46`),给了真城市等于在评论区挂个「我是机器人」的标。 `likeCount` 分布也比短剧平得多——真实影视评论抽样 70 条,0 赞占八成: ``` 72% -> 0 16% -> 1~3 8% -> 4~20 3.4% -> 21~80 0.6% -> 81~300 ``` 再按文案长短压上限(≤4 字最多 20 赞,≤8 字最多 80)。 其余坑和 dramacmt 完全一致,不重复写:`status` 必须直接写 `1`(App 发评论写的是 `2`,列表只认 `1`)、`type` 是 `"VIDEO"` 而 `objType` 才是 `"video"`、 `tousername` 落库键名是小写的、`user` 表 `devID` 上是非 sparse 唯一索引。 ## 文案 `content.go` 里 224 条,互不重复,以 2~14 字的短句为主(对齐真实评论的语感)。 真实评论里占比不小的三类内容**故意没有收进来**:约炮求联系留地区的、涉及年龄的、 非自愿表述的。这三类是审核该删的东西,不该由我们批量生产。 ## 机器人用户 沿用 dramacmt 的 uid 池并往上扩到 **1001~6000**(5,000 个)。23 万条评论摊到 5,000 个用户是每人 ~46 条;只用 dramacmt 那 400 个的话每人 580 条,同一个头像 昵称在评论区刷屏。已存在的 uid 不覆盖,可以重复跑。 ## 用法 ```bash go build -o /tmp/vidcmt ./scripts/vidcmt/ # 干跑,看分层后会写多少 /tmp/vidcmt --dst "$DST_TANGGUO" --db tangguo --dry-run # 正式跑(跑完自动重算计数) /tmp/vidcmt --dst "$DST_TANGGUO" --db tangguo # 只重算计数,不铺评论 /tmp/vidcmt --dst "$DST_TANGGUO" --db tangguo --recount # 调试:只铺 5 个视频,固定种子便于复现,跳过重算 /tmp/vidcmt --dst "$DST_TANGGUO" --db tangguo --limit 5 --seed 7 --no-recount ``` 默认只给**没有任何可见评论**的视频铺(`--only-empty`),所以中断了直接重跑, 已经铺过的会被跳过。`--db` 必须显式传:URI 里的 `authSource` 通常是 `admin`。 ## 撤回 ```js // 软删这批评论 db.comment.updateMany({isRobot: true, objType: "video", userID: {$gte: 1001, $lte: 6000}}, {$set: {isDelete: true}}) ``` 硬删把 `$set` 换成 `deleteMany`。两种都做完后跑一次 `--recount`, 计数会自己对齐,不用手工回减。