vidcmt 给在线影视(video_info 里 newsType=SP)铺机器人评论,条数按 fakePlayCount 分层(热门 20~50 条,长尾 1 条),而不是像短剧那样一刀切—— 真实影视评论区本来就稀,统一铺 20~50 既是 300 万条文档也一眼假。 跑完自动重算 commentCount / fakeCommentCount,口径取自后端自己的修复函数 rebuildSingleObjCommentCount 的 video 分支,顺带修掉 fakeCommentCount 被 减穿成负数的历史脏数据。 同时修正 dramacmt:city 改成写 "-"。发评论路径里 GetLocationByIP 的调用 是注释掉的,线上真实评论没有一条带归属地,给真城市等于在评论区挂个 「我是机器人」的标。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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 不覆盖,可以重复跑。
用法
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。
撤回
// 软删这批评论
db.comment.updateMany({isRobot: true, objType: "video", userID: {$gte: 1001, $lte: 6000}},
{$set: {isDelete: true}})
硬删把 $set 换成 deleteMany。两种都做完后跑一次 --recount,
计数会自己对齐,不用手工回减。