{"record":{"id":"622f7358b27fe94c","repo":"xpzouying/xiaohongshu-mcp","slug":"w-622f73","errorCode":null,"errorMessage":"无法找到提交按钮: %w","messagePattern":"无法找到提交按钮: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"xiaohongshu/comment_feed.go","lineNumber":174,"sourceCode":"\thumanize.Delay(ctx, humanize.AfterClick)\n\n\t// 查找回复输入框\n\tinputEl, err := page.Element(\"div.input-box div.content-edit p.content-input\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"无法找到回复输入框: %w\", err)\n\t}\n\n\t// 输入内容\n\tif err := humanize.Type(ctx, inputEl, content); err != nil {\n\t\treturn fmt.Errorf(\"输入回复内容失败: %w\", err)\n\t}\n\n\thumanize.Delay(ctx, humanize.AfterType)\n\n\t// 查找并点击提交按钮\n\tsubmitBtn, err := page.Element(\"div.bottom button.submit\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"无法找到提交按钮: %w\", err)\n\t}\n\n\tif err := humanize.Click(submitBtn); err != nil {\n\t\treturn fmt.Errorf(\"点击提交按钮失败: %w\", err)\n\t}\n\n\thumanize.Delay(ctx, humanize.AfterClick)\n\n\t// 就地校验：回复应在评论区渲染出现，否则判定未成功。\n\tif !waitCommentRendered(page, content, 4*time.Second) {\n\t\tlogrus.Warnf(\"回复提交后未在评论区渲染，判定未成功: feed=%s\", feedID)\n\t\treturn fmt.Errorf(\"回复未确认成功：提交后未在评论区出现（可能账号被限制或发送失败）\")\n\t}\n\n\tlogrus.Infof(\"回复评论成功并已确认\")\n\treturn nil\n}\n","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/xpzouying/xiaohongshu-mcp/blob/332d196854a9eac0d2b8c2c0e3d0cc43139d724c/xiaohongshu/comment_feed.go#L156-L192","documentation":"ReplyToComment 输入回复内容后，用 div.bottom button.submit 查找提交按钮失败：按钮未渲染（内容校验未过、输入被清空）或选择器与页面结构不符。","triggerScenarios":"调用 ReplyToComment 并走到提交阶段：点击回复按钮后输入框未正确激活（div.bottom button.submit 不存在或被隐藏）、页面被风控/验证码打断、DOM 结构改版、或页面超时（page.Timeout(5m) 已到期）。","commonSituations":"小红书前端改版导致选择器失效；账号被风控后输入框进入受限状态；导航到 feed 详情页实际落在验证码/登录页；回复框是自绘组件而 submit 按钮类名不同。","solutions":["先人工复现：在浏览器打开同一 feed，点击目标评论的回复按钮，确认 div.bottom button.submit 是否出现，必要时更新选择器","检查 checkPageAccessible 是否通过，排查是否被重定向到登录/验证码页","确认账号未被风控（换账号或降低操作频率测试）","增加提交按钮查找前的等待（等待输入框获得焦点后再查）或延长 rod 超时"],"exampleFix":"// before\nsubmitBtn, err := page.Element(\"div.bottom button.submit\")\nif err != nil {\n    return fmt.Errorf(\"无法找到提交按钮: %w\", err)\n}\n\n// after\n// 先确保输入框已激活，再用显式超时等待提交按钮\npage = page.Timeout(10 * time.Second)\nif p, err := page.Element(\"div.input-box div.content-edit p.content-input\"); err == nil {\n    p.MustClick()\n    humanize.Delay(ctx, humanize.AfterClick)\n}\nsubmitBtn, err := page.Element(\"div.bottom button.submit\")\nif err != nil {\n    return fmt.Errorf(\"无法找到提交按钮（可能被风控或页面改版）: %w\", err)\n}","handlingStrategy":"try-catch","validationCode":"err := action.ReplyToComment(ctx, feedID, token, commentID, userID, content)\nif err != nil && strings.Contains(err.Error(), \"无法找到提交按钮\") {\n    log.Warnf(\"feed %s 回复失败，页面状态异常: %v\", feedID, err)\n}","typeGuard":"func isSubmitButtonNotFound(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"无法找到提交按钮\")\n}","tryCatchPattern":"if err := action.ReplyToComment(ctx, feedID, token, commentID, userID, content); err != nil {\n    if isSubmitButtonNotFound(err) {\n        markFeedUnreplyable(feedID)\n        return\n    }\n    return err\n}","preventionTips":["升级前先在真实页面验证 div.bottom button.submit 选择器仍有效","保持登录态新鲜，避免带着过期 cookie 进入回复流程","把连续出现的 selector-not-found 作为页面改版/风控的早期告警","控制回复频率，避免触发风控导致输入框进入受限状态"],"tags":["browser-automation","selector","go-rod","dom"],"backgroundTag":"element-selector-not-found","analyzedSha":"332d196854a9eac0d2b8c2c0e3d0cc43139d724c","analyzedAt":"2026-09-05T22:22:55.988Z","contentChangedAt":"2026-09-05T22:22:55.988Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}