CDP 输入合并:保持悬停交互的一致性
为单个 BrowserContext 配置有界的纯鼠标悬停移动批处理,同时保持点击、拖拽、滚轮、键盘、触摸和触控笔输入路径不变。
CDP 客户端通常一次发送一个鼠标移动命令。客户端发送一个坐标,等待命令完成,再发送下一个坐标。这种顺序便于控制,但快速自动化悬停与原生指针移动流到达浏览器事件队列的方式可能不同,页面也可能观察到事件时序差异。
BotBrowser 提供了一个上下文级选项,用于需要更一致悬停路径的工作流:--bot-cdp-coalesce。该选项默认关闭。为 BrowserContext 开启后,BotBrowser 接受一小段连续的纯鼠标悬停移动,保持原始顺序,再作为短的串行批次转交浏览器。最终页面事件以及浏览器自身的事件合并仍由浏览器引擎决定。
从默认设置开始
大多数浏览器自动化不需要特殊输入选项。工作流使用点击、表单、键盘输入、滚动、拖放、触摸手势或触控笔时,保持选项关闭。默认路径保留普通的 CDP 完成行为,不会改变已经满足交互要求的工作流。
只有在一个上下文通过 CDP 高频发送纯鼠标悬停移动,并且需要浏览器让这些坐标在输入队列中形成有限重叠时,才开启该选项。工具提示、接近指针时打开的菜单、悬停卡片以及对桌面指针位置敏感的界面,都是合适的例子。选项属于上下文,因此同一个浏览器中的另一个上下文仍可使用默认值。
这个选项不会随机化指针轨迹,也不会创建新的移动坐标。客户端仍决定坐标和坐标顺序。BotBrowser 只控制已接受悬停移动在短输入窗口中的转交方式,页面看到的最终位置仍是最后一个坐标。
配置一个 BrowserContext
通过 BotBrowser 启动器提供的上下文配置入口设置 --bot-cdp-coalesce。在上下文创建第一个页面或 worker 之前完成配置。把这个值与浏览器版本、profile 选择和自动化包版本一起记录,后续验证才能复现同一输入策略。
单独的 flag 表示开启,显式的 --bot-cdp-coalesce=true 也表示开启。部署模板可能自动加入 flag 时,使用 --bot-cdp-coalesce=false 明确保持默认行为。把它当作上下文身份配置,不要计划在上下文已经服务页面时切换它。
一个进程创建多个上下文时,为每个上下文设置明确值。开启的上下文不会替同一浏览器的兄弟上下文开启选项,新上下文也必须获得自己的值。让 flag 与 profile 和上下文声明放在一起,并在运行元数据中记录开关状态。页面脚本不能控制 CDP 命令何时完成,也不能控制浏览器输入队列怎样接收事件,因此不能替代该选项。
哪些移动会进入批次
只有纯鼠标悬停移动进入上下文批次。指针没有按下按钮,不处于相对移动模式,事件是普通鼠标移动。接近目标、查看悬停状态或穿过桌面界面时使用的移动属于这一范围。
鼠标按下和抬起、活动拖拽及拖拽转换、滚轮、键盘和文本输入、触摸、触控笔以及相对鼠标移动都保持原路径。这些边界保留离散动作和其他设备类型的含义。点击保留正常按钮状态和完成行为,拖拽保留转换顺序,滚轮保留增量和时序。
修饰键和按钮状态也属于判断条件。按钮按下时产生的移动是拖拽或其他活动指针操作的一部分,不是纯悬停,会继续使用正常路径。这样可以避免悬停批次跨过指向控件和操作控件之间的边界。
批次如何交付
上下文接受一小段符合条件的悬停移动,并按原始顺序转交。批次有界,因此页面卡顿或异常长的移动流不会建立无限队列。批次也只存活很短时间,范围限于高频移动,不会成为通用输入缓冲。
每个 CDP 命令保留一个完成结果。接受的悬停命令可以在上下文接受其转交后完成,页面仍会从浏览器输入路径收到对应移动。非悬停输入继续使用正常的 浏览器确认路径。另一种输入需要通过同一路径时,待处理的悬停移动会先清空,以保持对用户有意义的可见顺序。
浏览器引擎决定这些坐标如何成为页面事件。当事件调度把相邻移动合并时,页面可能看到主事件以及一组合并子事件。BotBrowser 不伪造子事件,不重写时间戳,也不替换最终坐标。页面事件数量可能随着 浏览器调度、页面工作、主机负载和客户端流变化。不要测试固定事件数,应测试用户可见结果、动作顺序、命令完成和最终指针位置。
串行调用与页面行为
Puppeteer 和 Playwright 集成常常逐条等待调用完成,再开始下一个调用。对于点击等离散动作,这是有用的完成契约。对于长悬停路径,每个坐标都等待完成会阻止多个普通移动同时处于浏览器队列中。
开启上下文选项后,客户端仍可以保持串行命令写法。上下文接受一小组纯悬停移动,再按顺序转交。调用方不需要生成第二条轨迹、加入随机等待或注入页面级 pointer 事件。这个变化只影响交付,不会改善轨迹本身。稀疏路径仍然稀疏,突然跳跃仍然存在;需要特定目标序列时,应单独调整客户端坐标和时序。
应用逻辑也不会改变。只在停留后打开的工具提示仍然需要停留,要求指针穿过特定区域的菜单仍然需要那段路径。合并帮助浏览器以接近原生队列的方式接收密集悬停流,但不会替代应用自身的交互规则。
把动作与移动分开
用悬停步骤抵达控件,再用普通点击步骤激活它。不要依赖悬停合并传递按钮转换。拖放应通过支持的拖拽路径完成完整序列,并单独验证放置结果。工具提示没有出现时,检查悬停路径、目标几何和页面状态;点击没有激活时,检查焦点、命中测试和点击序列;拖拽没有完成时,检查源、目标以及应用是否接受。
页面通过悬停显示按钮时,验证指针抵达后显示状态出现,随后按钮接受普通点击。把上下文 flag 记入运行记录,后续操作员就能区分输入交付变化与选择器或布局变化。
上下文隔离与生命周期
选项作用于 BrowserContext。Context A 可以开启,Context B 可以关闭,即使它们运行在同一浏览器进程中。设置不会泄漏到其他 target、页面、worker 或新建上下文。
工作结束后照常关闭上下文。如果移动流期间页面或 target 被替换,旧移动不应继续进入替换后的 target。对新页面状态开始新的工作流。导航时等待新页面就绪,再运行新界面需要的移动。上下文重建时重新应用选项,因为行为仍是每个上下文的选择。
实用验证流程
准备一个包含工具提示、悬停菜单或悬停卡片的受控页面或批准测试路由。指针抵达目标后,应出现操作员能确认的可见状态变化。先创建关闭选项的上下文,沿同一路径移动指针,记录悬停状态和最终坐标。再创建开启选项的独立上下文,重复相同路径并记录相同结果。
保持浏览器版本、profile、viewport、页面状态、客户端包和坐标列表不变,一次只改变一个变量。生产工作流可在悬停状态出现后增加点击,再验证目标页面状态。增加一个不依赖悬停的表单字段或普通按钮。只有实际使用拖拽、滚轮、触摸或触控笔时,才加入对应检查。
成功标准是悬停状态可达,动作顺序正确,每个命令只有一个完成结果,最终坐标没有丢失。成功不等于每次运行都得到相同的合并列表或相同的页面事件数。
兼容性与排查
这个选项只影响 CDP 交付的纯鼠标悬停移动,不改变浏览器身份、网络路由、cookies、存储、权限、viewport 或 profile 数据。移动端和触摸工作流应使用触摸输入和移动 viewport。触控笔界面应使用触控笔输入,相对移动应用应使用正常输入路径。
如果选项没有可见效果,确认上下文在第一个页面前收到了 flag,移动确实是纯鼠标悬停,页面也确实使用悬停状态。运行之间页面事件数变化是 浏览器调度或页面负载变化的正常结果,应比较悬停状态、动作顺序、命令完成和最终坐标。两个上下文行为不同,则检查各自的显式值、profile、浏览器版本、viewport、页面状态和坐标列表。CDP 命令完成与应用可见准备状态是不同条件,应等待工作流需要的页面信号。
--bot-cdp-coalesce 为一个狭窄的交互类别提供了明确选择。默认保持关闭。对发送密集纯鼠标悬停移动且需要短串行批处理的上下文开启它,让其他输入类型保持标准路径,并把设置与上下文配置一同记录。