xpzouying/xiaohongshu-mcp · error
未找到评论 (commentID: %s, userID: %s)
Error message
未找到评论 (commentID: %s, userID: %s)
What it means
findCommentElement 完成全部滚动/展开/懒加载流程后仍未匹配到 commentID(或 userID)对应的评论:评论已删除、不可见,或 ID 无效。与超时分支不同,此时评论区已搜索完毕。
Source
Thrown at xiaohongshu/comment_feed.go:270
break
}
}
// 5. 滚到最后一条评论再继续下滚,触发懒加载
if currentCount > 0 {
if elements, err := page.Timeout(2 * time.Second).Elements(".comment-item"); err == nil && len(elements) > 0 {
if err := elements[len(elements)-1].ScrollIntoView(); err != nil {
logrus.Debugf("滚动到最后一条评论失败: %v", err)
}
}
humanize.Delay(ctx, humanize.BetweenScroll)
}
humanScroll(ctx, page, "normal", false, 1)
humanize.Delay(ctx, humanize.BetweenScroll)
}
return nil, fmt.Errorf("未找到评论 (commentID: %s, userID: %s)", commentID, userID)
}
// lookupComment 在当前已渲染的评论里查找目标,找不到返回 nil。
func lookupComment(page *rod.Page, commentID, userID string) *rod.Element {
if commentID != "" {
if el, err := page.Timeout(2 * time.Second).Element(fmt.Sprintf("#comment-%s", commentID)); err == nil && el != nil {
return el
}
}
if userID == "" {
return nil
}
// 一级和二级评论都带 .comment-item;.parent-comment 会把整个楼层一起匹配上。
elements, err := page.Timeout(2 * time.Second).Elements(".comment-item")
if err != nil {
return nilView on GitHub (pinned to 332d196854)
Solutions
- 核对传入的 commentID 是否与 DOM 的 #comment-{commentID} 格式一致(去掉多余前缀/后缀)
- 确认目标评论仍存在:手动打开 feed 页检查该评论是否可见
- 确认 userID 正确且该用户在该 feed 下确有可见评论
- 刷新抓取数据,用最新的评论列表重新定位评论 ID
Example fix
// before
commentID := "665f1a2b000000001234abcd" // 来自旧数据
err := action.ReplyToComment(ctx, feedID, token, commentID, userID, content)
// after:先做格式与新鲜度校验
if !isValidCommentID(commentID) {
return fmt.Errorf("commentID 格式非法: %q", commentID)
}
if time.Since(commentFetchedAt) > 24*time.Hour {
return errors.New("评论数据过期,请先刷新评论列表再回复")
}
err := action.ReplyToComment(ctx, feedID, token, commentID, userID, content) Defensive patterns
Strategy: validation
Validate before calling
func isValidCommentID(id string) bool {
// 24 位十六进制(小红书评论 ID 形态),按实际格式调整
if len(id) != 24 { return false }
for _, c := range id {
if !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f')) { return false }
}
return true
}
// 调用前
if !isValidCommentID(commentID) || userID == "" {
return errors.New("非法 commentID 或缺失 userID,拒绝回复")
} Type guard
func isCommentNotFoundErr(err error) bool {
return err != nil && (strings.Contains(err.Error(), "未找到评论") ||
strings.Contains(err.Error(), "无法找到评论"))
} Try / catch
err := action.ReplyToComment(ctx, feedID, token, commentID, userID, content)
if isCommentNotFoundErr(err) {
// 评论已删除/不可见:刷新评论列表数据,跳过该条并记录
invalidateCachedComment(commentID)
log.Infof("评论 %s 已不存在,跳过", commentID)
return nil
}
return err Prevention
- 回复前校验 commentID 格式,确保能拼出合法的 #comment-{id} 选择器
- 使用最近一次抓取的评论数据,不要拿超过一天的旧 ID 回复
- 同时提供 commentID 和 userID(双保险),提高查找命中率
- 对"未找到评论"分类:数据过期 vs 评论被删,分别处理缓存与重试
When it happens
Trigger: ReplyToComment 传入的 commentID 在页面无 #comment-{id} 节点且按 data-user-id 也匹配不到 userID:评论已被删除、commentID 格式与 DOM 不符、或该用户在该 feed 下无可见评论。
Common situations: 用旧抓取数据里的 commentID 回复(评论已删/被隐藏);commentID 与 DOM id 约定不符(DOM 是 #comment-xxx 而传入 id 带其他前缀);userID 传错或目标评论被折叠。
Related errors
AI-assisted analysis of xpzouying/xiaohongshu-mcp@332d196854 (2026-09-05).
Data as JSON: /api/errors/edfc14d0f1bad027.
Report an issue: GitHub.