Headless Chromium 点不动自定义组件?用 CDP 真实鼠标事件绕过
【摘要】 问题现象用 Playwright 或 Selenium 在无头 Chromium 里做自动化时,会遇到一类特别的按钮:por-checkbox、hwid-getAuthCode 这种 Web Component 封装的控件。用 element.click() 或者 dispatchEvent(new MouseEvent('click')) 完全没反应 —— DOM 上属性变了,业务逻辑就是...
问题现象
用 Playwright 或 Selenium 在无头 Chromium 里做自动化时,会遇到一类特别的按钮:por-checkbox、hwid-getAuthCode 这种 Web Component 封装的控件。用 element.click() 或者 dispatchEvent(new MouseEvent('click')) 完全没反应 —— DOM 上属性变了,业务逻辑就是不执行。
根因:isTrusted
浏览器区分「真实用户输入」和「脚本合成事件」,前者 event.isTrusted === true。不少前端框架,以及带风控的登录组件,会在事件处理入口判断这个标志,为 false 就直接 return。所以无论怎么 dispatch,事件都到不了业务层。
几个无效的尝试
element.click():合成事件,isTrusted 为 false;dispatchEvent(new MouseEvent(...)):同上;- 直接改 DOM 属性再触发 change:React / Vue 受控组件会把值改回去;
- Playwright 的 force click:底层同样走 CDP,但命中点被遮挡时会打偏。
解法:走 CDP 的 Input 域
Chrome DevTools Protocol 的 Input.dispatchMouseEvent 是内核级输入,生成的事件 isTrusted === true,等价于真人按下鼠标。
const ws = new WebSocket('ws://127.0.0.1:9222/devtools/browser/<id>');
// attach 到目标页面拿到 sessionId 之后:
await send('Input.dispatchMouseEvent', {type:'mouseMoved', x, y}, sessionId);
await send('Input.dispatchMouseEvent', {type:'mousePressed', x, y, button:'left', clickCount:1}, sessionId);
await send('Input.dispatchMouseEvent', {type:'mouseReleased', x, y, button:'left', clickCount:1}, sessionId);
关键细节:坐标怎么取
- 坐标是 CSS 像素,不是截图像素。截图会被 devicePixelRatio 缩放,直接拿截图上的坐标去点必然偏移;
- 元素必须在视口内。先
scrollIntoView({block:'center'}),再取getBoundingClientRect(); - 取文字节点父元素的中心,不要用容器左上角 —— 外层 div 往往带 padding,左上角点不到。
通用封装:按文字点
function tapByText(text){
const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT);
let n;
while (n = walker.nextNode()) {
if (n.textContent.trim() === text) {
const r = n.parentElement.getBoundingClientRect();
return { x: r.x + r.width / 2, y: r.y + r.height / 2 };
}
}
return null;
}
拿到坐标后交给 CDP 点击,成功率接近真人操作。这套方式在登录页的「获取验证码」、博客发布页的「免责声明」勾选框上都验证过,都是一点就过。
小结
自动化不是「能找到元素就能点」,而是「能不能产生可信输入」。当合成事件被 isTrusted 挡在门外时,退回到浏览器输入层,用 CDP 的 Input 域,是最短的那条路。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)