You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 23:06:08