Delphi 10.4.1 EdgeBrowser 模拟操作网页方法


本文整理自网络,侵删。

 
以往一直用TWebBrowser 或者 C++ Builder 中的TCcpWebBrowser来写网页模拟操作
这两个控件可以使用WebBrowser.OleObject.document、WebBrowser.Document As IHTMLDocument2来实现大部分的操作
发现这两者都是依赖于IE内核,虽然可以设定IE 11内核,但是今年微软公布11月底停止更新了
所以可以考虑使用微软推出的Edge浏览器

进入正题:

Delphi 10.4.1 新增的TEdgeBrowser控件
研究了一下发现该控件似乎不再支持像TWebBrowser那样使用IHTMLDocument2方法了
Google一下发现几乎没有资料可寻,在GW某个论坛看到说被其他方式代理了,翻了一下Edge类,在类中有这么一个方法:

    /// <summary>
    ///   Execute JavaScript code from the javascript parameter in the current top level document rendered in the
    ///   WebView, even if ScriptEnabled is False
    /// </summary>
    procedure ExecuteScript(const JavaScript: string);

对应回调事件

  当 ExecuteScript 执行完成后回调结果给 OnExecuteScript 
  /// <summary>
  ///   Event handler type for the OnExecuteScript event
  /// </summary>
  TExecuteScriptEvent = procedure (Sender: TCustomEdgeBrowser; AResult: HResult; const AResultObjectAsJson: string) of object;

OnExecuteScript 包含两个参数,AResult 返回状态,AResultObjectAsJson 返回数据
经过测试发现,AResultObjectAsJson 默认回调过来的数据如果不是Json而是字符串,那么该字符串会被加上双引号,如 “button click success”,AResultObjectAsJson 的返回值经过测试,好像只返回最后一次被赋值的变量或被修改过的元素值

方法:
下载WebView2的dll支持库放入程序目录下
链接:https://pan.baidu.com/s/1ASnrkr8v893egwSoCVNcjg
提取码:igjt

下载MicrosoftEdgeDev浏览器,安装好桌面会出现Microsoft Edge Dev图标
链接:https://pan.baidu.com/s/1OrGtyYpNdM1ph5qNyHFU1Q
提取码:acap

在这里插入图片描述


以上工作做好以后,即可进行开发了
1.界面拖入EdgeBrowser控件
2.在控件事件中双击OnExecuteScript创建一个回调事件
3. EdgeBrowser1.ExecuteScript(‘你的JavaScript脚本’);

假定我们打开的页面有这样一个按钮:

<input class="class1" id="button1" type="text" value="">

那么在我的程序目录下写一个名为 test.js 的文件,保存格式为utf-8,用于修改网页input的value值。
JavaScript代码如下:注意脚本不用加

<script>
</script>

,加了之后好像无法运行

var Result = null; //这个作为最后处理的结果返回值
var item = document.getElementById(“button1”);
item.velue = “123456”;
//OnExecuteScript回调返回 AResultObjectAsJson 的值是 “123456”
//如果加上这一条
Result = “输入成功”;
//那么 OnExecuteScript回调返回 AResultObjectAsJson 的值是 “输入成功”

<br>

变通一下,将这个脚本写成模板
```javascript
//用于向页面input元素输入值
var Result = null;//这个作为最后处理的结果返回值
var idName = "%s";//这个作为你要替换的元素ID
var mValue = "%s";//这个作为你要写入的值
var item = document.getElementById(idName );
if(item != null){
item.focus();
item.value = mValue;
//这个就是最后OnExecuteScript返回的值,如果没有这一条,那么返回的应该是 item.value 的值
Result = "set " + mValue + " success";
//当然也可以返回json、整数
Result = {"status":true, "text":"输入成功"};
}
//如果没有设定Result 的值,那么结果返回的肯定是你修改的值

定义一个函数用来加载js文件并格式化数据

function getJavaScript(ScriptPath:string; Args:array of string);
var AList:TStringList;
I:Integer;
begin
Alist:= TStringList.Create;
Alist.LoadFromFile(ScriptPath, TEncoding.UTF8);
for I := Low(Args) to High(Args) do
  begin
  //StringReplace函数 需要引用 System.SysUtils
    AList.Text := StringReplace(AList.Text, '%s', Args[I], []);
  end;
Result:= AList.Text;
AList.Free;
end;

读取脚本并运行

procedure TForm1.Button1Click(Sender: TObject);
var AText:string;
begin
AText:= getJavaScript('test.js', ['button1', '123456']);
EdgeBrowser1.ExecuteScript(AText);
end;

这样就可以方便的调用JavaScript脚本了
需要注意的是
EdgeBrowser1.ExecuteScript();
不能在线程中调用,如果是匿名线程需这样

TThread.Synchronize(TThread.CurrentThread, procedure
begin
EdgeBrowser1.ExecuteScript('你的脚本');
end);

如果是线程,建议在当前单元定义一个全局变量,用于存放OnExecuteScript的返回值
写一个线程函数用于运行并等待回调,回调一般执行失败AResultObjectAsJson 的值是null,成功则返回脚本中的值,我测试了一下这样效果很理想,期待有更好的解决办法

function TForm1.ExecJavaScript(AScript: string): string;
begin
  ScriptResult:= '';//全局变量
  TThread.Synchronize(TThread.CurrentThread, procedure begin
    EdgeBrowser1.ExecuteScript(AScript);
  end);

  while not TThread.CheckTerminated do
  begin
    Sleep(50);
    if ScriptResult <> '' then break;
  end;

  Result:= ScriptResult;
end;

回调

procedure TForm1.EdgeBrowser1ExecuteScript(Sender: TCustomEdgeBrowser;
  AResult: HRESULT; const AResultObjectAsJson: string);
begin
  ScriptResult:= AResultObjectAsJson;
end;

线程中直接调用ExecJavaScript就可以了,可以循环执行,直到结果不为null
线程中调用

    Script1:= GetJavaScript('setElementValueById.js', ['J_payeeShowAccount', "123456789"]);
    while not TThread.CheckTerminated do
    begin
      Sleep(50);
      if ExecJavaScript(Script1) <> 'null' then break;
    end;

目前好像就只能这样了,流畅度好像比IE要舒服。。。。
期待更好的方法。。。。
建议使用Json作为返回值,相对来说复杂点,个人比较懒,哈哈。。

来源:https://blog.csdn.net/zhou752947/article/details/109542365

相关阅读 >>

Delphi idhttp控件学习(图片下载)

Delphi如何获取qq2010聊天窗口句柄

Delphi图片base64编码

重新组织编写Delphi的md2、md4、md5类

Delphi获取开机时间代码

Delphi 程序窗体最大化、组件居中显示代码

Delphi 编写activex控件(ocx控件)的知识和样例

Delphi 获取当前系统版本号

Delphi 读取eset nod32 的用户名与密码

Delphi中使用低层钩子 屏蔽win、ctrl+esc、alt+tab、alt+f4

更多相关阅读请进入《Delphi》频道 >>



打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...