Delphi安卓环境下使用TWebBrowser填充提交HTML表单的方法
安卓平台Delphi TWebBrowser操作表单输入与提交实现方案
Windows平台下基于MSHTML接口直接操作DOM的方案在安卓端完全无法使用:安卓端TWebBrowser底层封装的是系统自带Chromium内核WebView,没有暴露Windows平台的COM DOM接口,直接注入JavaScript实现是稳定性、兼容性最优的方案,不需要额外引入第三方JNI桥接库。
前置准备
- 给TWebBrowser组件绑定
DidFinishLoad事件,所有DOM操作必须等网页完全加载完成后再执行 - 确认项目已开启安卓平台Internet权限,避免WebView加载、JS执行异常
- 代码中提前引用
System.SysUtils单元,后续字符串处理会用到内置函数
核心实现
1. 封装通用JS执行方法
安卓端TWebBrowser原生提供JS执行接口,直接封装即可复用:
procedure TMainForm.RunJS(const AJSCode: string); begin WebBrowser1.EvaluateJavaScript(AJSCode); end;
2. 给输入框赋值
不要直接修改input的value属性——现在绝大多数站点用Vue、React类前端框架,直接改value不会触发框架状态更新,会出现“界面看着填了值、提交时空值报错”的问题,必须模拟原生输入行为:
procedure TMainForm.SetInputValue(const ACssSelector, AInputValue: string); var LExecJs: string; begin LExecJs := Format( '(function(){' + ' var targetInput = document.querySelector(%s);' + ' if(!targetInput) return;' + ' // 调用原生value赋值器,触发框架监听' + ' var nativeValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set;' + ' nativeValueSetter.call(targetInput, %s);' + ' // 派发input事件,兼容所有前端校验逻辑' + ' targetInput.dispatchEvent(new Event("input", {bubbles: true}));' + '})();', [QuotedStr(ACssSelector), QuotedStr(AInputValue)] ); RunJS(LExecJs); end;
参数
ACssSelector传标准CSS选择器即可:比如选name为username的输入框传'input[name="username"]',选id为password的密码框传'#password'。
3. 触发表单提交
可以直接调用表单的submit方法,也可以触发提交按钮的点击事件,优先选表单提交的方式,稳定性更高:
procedure TMainForm.TriggerSubmit(const AFormSelector: string = 'form'); var LExecJs: string; begin LExecJs := Format( '(function(){' + ' var targetForm = document.querySelector(%s);' + ' if(targetForm) targetForm.submit();' + '})();', [QuotedStr(AFormSelector)] ); RunJS(LExecJs); end;
如果需要点击指定提交按钮,替换对应JS逻辑即可:
// 触发type为submit的按钮点击 RunJS('document.querySelector(''button[type="submit"]'').click();');
调用示例
在网页加载完成事件中按顺序执行逻辑即可,注意加短延迟避免值未同步就提交:
procedure TMainForm.WebBrowser1DidFinishLoad(ASender: TObject); begin // 填充用户名 SetInputValue('input[name="username"]', 'your_account'); // 填充密码 SetInputValue('input[name="password"]', 'your_password'); // 延迟100ms提交,等待输入事件全部执行完成 TThread.ForceQueue(nil, procedure begin TriggerSubmit(); end, 100); end;
常见踩坑说明
- 不要在调用
Navigate后立刻执行DOM操作,必须等DidFinishLoad事件触发,否则会因为DOM未渲染完成找不到节点 - 同域嵌套iframe的场景,需要先获取对应iframe的
contentDocument再选节点,直接在根document下无法选中iframe内的输入框;跨域iframe受浏览器安全策略限制,无法直接操作 - JS代码尽量写ES5标准语法,低版本安卓自带WebView内核版本较低,不支持箭头函数、可选链等新特性,会导致JS执行失败
- 如果页面有滑动验证码、人机校验类逻辑,注入JS的方式无法绕过,需要额外做对应适配
内容的提问来源于stack exchange,提问作者SMA
相关产品推荐
相关产品推荐

