{"record":{"id":"adf16af41d7a20a0","repo":"xpzouying/xiaohongshu-mcp","slug":"error-adf16a","errorCode":null,"errorMessage":"点击商品选择框失败","messagePattern":"点击商品选择框失败","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"xiaohongshu/publish.go","lineNumber":1327,"sourceCode":"\n\t// 5. 点击第一个商品的 checkbox（使用与工作代码相同的选择器）\n\tcheckbox, err := modal.Element(\".goods-list-normal .good-card-container .d-checkbox\")\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"未找到商品选择框\")\n\t}\n\n\t// 检查是否已经选中\n\tisChecked, err := checkbox.Eval(`(el) => {\n\t\treturn el.querySelector('.d-checkbox-simulator.checked') !== null ||\n\t\t\t   el.querySelector('input[type=\"checkbox\"]:checked') !== null;\n\t}`)\n\tif err == nil && isChecked.Value.Bool() {\n\t\tslog.Info(\"商品已选中，跳过\", \"keyword\", keyword)\n\t\treturn nil\n\t}\n\n\tif err := humanize.Click(checkbox); err != nil {\n\t\treturn errors.Wrap(err, \"点击商品选择框失败\")\n\t}\n\n\trandomDelay := 800 + rand.Intn(700)\n\ttime.Sleep(time.Duration(randomDelay) * time.Millisecond)\n\n\tslog.Info(\"已选择商品\", \"keyword\", keyword)\n\treturn nil\n}\n\n// clickModalSaveButton 点击保存按钮\nfunc clickModalSaveButton(modal *rod.Element) error {\n\t// 查找保存按钮（参考工作代码：直接查找并点击，不强制要求找到）\n\tbtn, err := modal.Element(\".goods-selected-footer button\")\n\tif err == nil && btn != nil {\n\t\tif err := humanize.Click(btn); err != nil {\n\t\t\tslog.Warn(\"点击保存按钮失败\", \"error\", err)\n\t\t} else {\n\t\t\tslog.Info(\"已点击保存按钮\")","sourceCodeStart":1309,"sourceCodeEnd":1345,"githubUrl":"https://github.com/xpzouying/xiaohongshu-mcp/blob/332d196854a9eac0d2b8c2c0e3d0cc43139d724c/xiaohongshu/publish.go#L1309-L1345","documentation":"searchAndSelectProduct 已定位商品勾选框、确认未选中后 humanize.Click 点击失败：勾选框被遮挡或列表在点击瞬间重渲染，商品未能选中。","triggerScenarios":"humanize.Click 执行期间：元素被遮挡（覆盖层/浮层）；DOM 在点击瞬间被 React 重渲染替换导致 detached；页面导航或弹窗关闭使元素句柄失效；humanize 内部滚动到元素失败。","commonSituations":"搜索结果加载后 500ms 内前端又重排了列表（sleep 太短）；页面弹出新的提示遮罩；小红书对自动化点击的风控拦截导致页面无响应；浏览器标签页被切换/最小化影响 humanize 的鼠标轨迹模拟。","solutions":["重试整个 searchAndSelectProduct 流程（重新搜索、重新定位、再点击），瞬时 detached 通常一次重试即可成功","点击前用 checkbox.WaitStable / WaitVisible 确认元素稳定后再点","改用 JS 点击兜底：checkbox.Eval(`(el) => el.click()`)","增加渲染后等待时间（500ms 太短），或等待 checkbox 的位置稳定"],"exampleFix":"// before\nif err := humanize.Click(checkbox); err != nil {\n    return errors.Wrap(err, \"点击商品选择框失败\")\n}\n// after\nif err := checkbox.WaitStable(300 * time.Millisecond); err != nil {\n    return errors.Wrap(err, \"等待商品选择框稳定失败\")\n}\nif err := humanize.Click(checkbox); err != nil {\n    // 兜底：JS 直接触发 click\n    if _, jsErr := checkbox.Eval(`(el) => el.click()`); jsErr != nil {\n        return errors.Wrap(jsErr, \"点击商品选择框失败\")\n    }\n}","handlingStrategy":"retry","validationCode":"// 点击前确认元素可见且稳定\nif err := checkbox.WaitVisible(); err != nil {\n    return errors.Wrap(err, \"checkbox 不可见\")\n}\nif err := checkbox.WaitStable(300 * time.Millisecond); err != nil {\n    return errors.Wrap(err, \"checkbox 未稳定\")\n}","typeGuard":"func clickable(el *rod.Element) bool {\n    if el == nil {\n        return false\n    }\n    return el.MustVisible()\n}","tryCatchPattern":"const maxRetry = 3\nvar lastErr error\nfor i := 0; i < maxRetry; i++ {\n    if err := humanize.Click(checkbox); err == nil {\n        lastErr = nil\n        break\n    } else {\n        lastErr = err\n        time.Sleep(time.Second)\n    }\n}\nif lastErr != nil {\n    return errors.Wrap(lastErr, \"点击商品选择框失败\")\n}","preventionTips":["点击前等待元素 stable，避免 React 重渲染导致 detached","保持浏览器窗口前台运行，避免 humanize 模拟鼠标被干扰","点击失败时用 JS click 作为兜底","给点击操作加有限次重试"],"tags":["click","automation","go-rod","dom"],"backgroundTag":"element-click-failed","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"}