WebView4Delphi - Delphi浏览器组件(Edge) (2) - 获取html源码

本文详细介绍了如何使用WVBrowser组件获取网页加载时的HTML源码和动态渲染后的内容,包括使用NavigationStarting事件、WebResourceResponseReceived和WebResourceResponseViewGetContentCompleted事件,以及执行JavaScript获取前端渲染内容的方法。

获取网页源码有两种情况,

1.直接请求页面加载时的htm源码,跟在浏览器里右键->查看页面源代码  的结果相同

定义变量

FURI: PChar;    //正在打开的URL地址
FSource: string;  //用于保存html代码

WVBrowser的NavigationStarting事件代码

procedure TForm1.WVBrowser1NavigationStarting(Sender: TObject; const aWebView: ICoreWebView2; const aArgs: ICoreWebView2NavigationStartingEventArgs);
begin
  FSource := '';
  aArgs.Get_uri(FURI);
end;

WVBrowser的WebResourceResponseReceived事件代码

procedure TForm1.WVBrowser1WebResourceResponseReceived(Sender: TObject; const aWebView: ICoreWebView2; const aArgs: ICoreWebView2WebResourceResponseReceivedEventArgs);
var
  TempArgs: TCoreWebView2WebResourceResponseReceivedEventArgs;
  TempResponse: TCoreWebView2WebResourceResponseView;
  TempRequest: TCoreWebView2WebResourceRequestRef;
  TempHandler: ICoreWebView2WebResourceResponseViewGetContentCompletedHandler;
begin
  try
    TempArgs := TCoreWebView2WebResourceResponseReceivedEventArgs.Create(aArgs);
    TempRequest := TCoreWebView2WebResourceRequestRef.Create(TempArgs.Request);

    if TempRequest.URI = FURI then
    begin
      TempHandler := TCoreWebView2WebResourceResponseViewGetContentCompletedHandler.Create(WVBrowser1, 1);

      TempResponse := TCoreWebView2WebResourceResponseView.Create(TempArgs.Response);
      TempResponse.GetContent(TempHandler);
    end;
  finally
    FreeAndNil(TempRequest);
    FreeAndNil(TempArgs);
    TempHandler := nil;
  end;
end;

WVBrowser的WebResourceResponseViewGetContentCompleted事件代码

procedure TForm1.WVBrowser1WebResourceResponseViewGetContentCompleted(Sender: TObject; aErrorCode: HRESULT; const aContents: IStream; aResourceID: Integer);
var
  TempOLEStream: TOLEStream;
  ss: TStringStream;
begin
  TempOLEStream := nil;

  if succeeded(aErrorCode) and assigned(aContents) then
  begin
    TempOLEStream := TOLEStream.Create(aContents);
    try
      TempOLEStream.Position := 0;
      if TempOLEStream.Size > 0 then
      begin
        ss := TStringStream.Create('', TEncoding.UTF8);
        ss.CopyFrom(TempOLEStream, TempOLEStream.Size);

        if aResourceID = 1 then
          FSource := ss.DataString;    //这里就是页面的html代码
        ss.Free;
      end;
    finally
      FreeAndNil(TempOLEStream);
    end;
  end;
end;

2.获取页面加载完成后的html源码,或者说实时获取当前的html源码,有的网站是前端JS渲染的,按照上面的方面获取不到想要的数据

WVBrowser1.ExecuteScript('document.documentElement.outerHTML;');

在ExecuteScriptCompleted事件中获取并进行处理

function TForm1.MyMatchEvaluator(const Match: TMatch): string;
var
  escape: string;
begin
  escape := Match.Value;
  if escape.StartsWith('\u') then
  begin
    var by: TBytes := TEncoding.UTF8.GetBytes(WideChar(StrToInt('$' + Copy(escape, 3, 4))));
    if IsDBCSLeadByte(by[0]) then
      Result := TEncoding.Unicode.GetString(by)
    else
      Result := StringOf(by);
  end
  else if escape = '\r' then
    Result := #13
  else if escape = '\n' then
    Result := #10
  else if escape = '\t' then
    Result := #9
  else if escape = '\\' then
    Result := '\'
  else if escape = '\"' then
    Result := '"'
  else
    Result := escape;
end;

procedure TForm1.WVBrowser1ExecuteScriptCompleted(Sender: TObject; aErrorCode: HRESULT; const aResultObjectAsJson: wvstring; aExecutionID: Integer);
var
  regex: TRegEx;
begin
  regex := TRegEx.Create('(\\[rnt\''\"]|\\u[0-9a-fA-F]{4})');

  //这里获取到的html源码还要去掉开头和结尾的双引号
  mmo1.Lines.Text := regex.Replace(aResultObjectAsJson, MyMatchEvaluator);
end;

两种方法的完整代码如下:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, uWVLoader,
  uWVBrowserBase, uWVBrowser, uWVWinControl, uWVWindowParent, Vcl.StdCtrls,
  Vcl.Mask, scGPExtControls, scControls, scGPControls, uWVTypeLibrary, uWVTypes,
  uWVCoreWebView2Args, uWVCoreWebView2Deferral, Vcl.ExtCtrls, Vcl.AxCtrls,
  Winapi.ActiveX, uWVCoreWebView2WebResourceRequest, uWVCoreWebView2Delegates,
  uWVCoreWebView2WebResourceResponseView, System.StrUtils,
  System.RegularExpressions;

type
  TForm1 = class(TForm)
    NavControlPnl: TscGPPanel;
    btn_home: TscGPGlyphButton;
    btn_back: TscGPGlyphButton;
    btn_forward: TscGPGlyphButton;
    btn_refresh: TscGPGlyphButton;
    edt_url: TscGPEdit;
    WVWindowParent1: TWVWindowParent;
    WVBrowser1: TWVBrowser;
    mmo1: TMemo;
    spl1: TSplitter;
    procedure WVBrowser1AfterCreated(Sender: TObject);
    procedure WVBrowser1DocumentTitleChanged(Sender: TObject);
    procedure edt_urlRightButtonClick(Sender: TObject);
    procedure WVBrowser1SourceChanged(Sender: TObject; const aWebView: ICoreWebView2; const aArgs: ICoreWebView2SourceChangedEventArgs);
    procedure WVBrowser1InitializationError(Sender: TObject; aErrorCode: HRESULT; const aErrorMessage: wvstring);
    procedure FormShow(Sender: TObject);
    procedure WVBrowser1NewWindowRequested(Sender: TObject; const aWebView: ICoreWebView2; const aArgs: ICoreWebView2NewWindowRequestedEventArgs);
    procedure btn_refreshClick(Sender: TObject);
    procedure btn_forwardClick(Sender: TObject);
    procedure btn_backClick(Sender: TObject);
    procedure btn_homeClick(Sender: TObject);
    procedure WVBrowser1WebResourceResponseViewGetContentCompleted(Sender: TObject; aErrorCode: HRESULT; const aContents: IStream; aResourceID: Integer);
    procedure WVBrowser1WebResourceResponseReceived(Sender: TObject; const aWebView: ICoreWebView2; const aArgs: ICoreWebView2WebResourceResponseReceivedEventArgs);
    procedure FormCreate(Sender: TObject);
    procedure WVBrowser1NavigationStarting(Sender: TObject; const aWebView: ICoreWebView2; const aArgs: ICoreWebView2NavigationStartingEventArgs);
    procedure WVBrowser1ExecuteScriptCompleted(Sender: TObject; aErrorCode: HRESULT; const aResultObjectAsJson: wvstring; aExecutionID: Integer);
  private
    FURI: PChar;
    FSource: string;
    { Private declarations }
    function MyMatchEvaluator(const Match: TMatch): string;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TForm1 }

procedure TForm1.btn_backClick(Sender: TObject);
begin
  WVWindowParent1.Browser.GoBack;
end;

procedure TForm1.btn_forwardClick(Sender: TObject);
begin
  WVWindowParent1.Browser.GoForward;
end;

procedure TForm1.btn_homeClick(Sender: TObject);
begin
//  WVWindowParent1.Browser.Navigate('http://www.baidu.com');

  WVBrowser1.ExecuteScript('document.documentElement.outerHTML;');
end;

procedure TForm1.btn_refreshClick(Sender: TObject);
begin
  WVWindowParent1.Browser.Refresh;
end;

procedure TForm1.edt_urlRightButtonClick(Sender: TObject);
begin
  WVBrowser1.Navigate(edt_url.Text);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  FURI := '';
  FSource := '';
  mmo1.Clear;
end;

procedure TForm1.FormShow(Sender: TObject);
begin
  WVBrowser1.CreateBrowser(WVWindowParent1.Handle);
end;

function TForm1.MyMatchEvaluator(const Match: TMatch): string;
var
  escape: string;
begin
  escape := Match.Value;
  if escape.StartsWith('\u') then
  begin
    var by: TBytes := TEncoding.UTF8.GetBytes(WideChar(StrToInt('$' + Copy(escape, 3, 4))));
    if IsDBCSLeadByte(by[0]) then
      Result := TEncoding.Unicode.GetString(by)
    else
      Result := StringOf(by);
  end
  else if escape = '\r' then
    Result := #13
  else if escape = '\n' then
    Result := #10
  else if escape = '\t' then
    Result := #9
  else if escape = '\\' then
    Result := '\'
  else if escape = '\"' then
    Result := '"'
  else
    Result := escape;
end;

procedure TForm1.WVBrowser1AfterCreated(Sender: TObject);
begin
  WVWindowParent1.UpdateSize;
end;

procedure TForm1.WVBrowser1DocumentTitleChanged(Sender: TObject);
begin
  Caption := WVBrowser1.DocumentTitle;
end;

procedure TForm1.WVBrowser1ExecuteScriptCompleted(Sender: TObject; aErrorCode: HRESULT; const aResultObjectAsJson: wvstring; aExecutionID: Integer);
var
  regex: TRegEx;
begin
  regex := TRegEx.Create('(\\[rnt\''\"]|\\u[0-9a-fA-F]{4})');

  mmo1.Lines.Text := regex.Replace(aResultObjectAsJson, MyMatchEvaluator);
end;

procedure TForm1.WVBrowser1InitializationError(Sender: TObject; aErrorCode: HRESULT; const aErrorMessage: wvstring);
begin
  ShowMessage(aErrorMessage);
end;

procedure TForm1.WVBrowser1NavigationStarting(Sender: TObject; const aWebView: ICoreWebView2; const aArgs: ICoreWebView2NavigationStartingEventArgs);
begin
  FSource := '';
  aArgs.Get_uri(FURI);
end;

procedure TForm1.WVBrowser1NewWindowRequested(Sender: TObject; const aWebView: ICoreWebView2; const aArgs: ICoreWebView2NewWindowRequestedEventArgs);
var
  newUrl: PChar;
begin
  if assigned(aArgs) then
  begin
    aArgs.Set_Handled(1);
    aArgs.Get_uri(newUrl);
    WVBrowser1.Navigate(newUrl);
  end;
end;

procedure TForm1.WVBrowser1SourceChanged(Sender: TObject; const aWebView: ICoreWebView2; const aArgs: ICoreWebView2SourceChangedEventArgs);
begin
  edt_url.Text := WVBrowser1.Source;
end;

procedure TForm1.WVBrowser1WebResourceResponseReceived(Sender: TObject; const aWebView: ICoreWebView2; const aArgs: ICoreWebView2WebResourceResponseReceivedEventArgs);
var
  TempArgs: TCoreWebView2WebResourceResponseReceivedEventArgs;
  TempResponse: TCoreWebView2WebResourceResponseView;
  TempRequest: TCoreWebView2WebResourceRequestRef;
  TempHandler: ICoreWebView2WebResourceResponseViewGetContentCompletedHandler;
begin
  try
    TempArgs := TCoreWebView2WebResourceResponseReceivedEventArgs.Create(aArgs);
    TempRequest := TCoreWebView2WebResourceRequestRef.Create(TempArgs.Request);

    if TempRequest.URI = FURI then
    begin
      TempHandler := TCoreWebView2WebResourceResponseViewGetContentCompletedHandler.Create(WVBrowser1, 1);

      TempResponse := TCoreWebView2WebResourceResponseView.Create(TempArgs.Response);
      TempResponse.GetContent(TempHandler);
    end;
  finally
    FreeAndNil(TempRequest);
    FreeAndNil(TempArgs);
    TempHandler := nil;
  end;
end;

procedure TForm1.WVBrowser1WebResourceResponseViewGetContentCompleted(Sender: TObject; aErrorCode: HRESULT; const aContents: IStream; aResourceID: Integer);
var
  TempOLEStream: TOLEStream;
  ss: TStringStream;
begin
  TempOLEStream := nil;

  if succeeded(aErrorCode) and assigned(aContents) then
  begin
    TempOLEStream := TOLEStream.Create(aContents);
    try
      TempOLEStream.Position := 0;
      if TempOLEStream.Size > 0 then
      begin
        ss := TStringStream.Create('', TEncoding.UTF8);
        ss.CopyFrom(TempOLEStream, TempOLEStream.Size);

        if aResourceID = 1 then
          FSource := ss.DataString;
        ss.Free;
      end;
    finally
      FreeAndNil(TempOLEStream);
    end;
  end;
end;

initialization
  GlobalWebView2Loader := TWVLoader.Create(nil);
  GlobalWebView2Loader.UserDataFolder := ExtractFileDir(Application.ExeName) + '\CustomCache';
  GlobalWebView2Loader.StartWebView2;

end.

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zsh0409

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值