从 Delphi 中提取 TWebBrowser 中的 iframe 内容

Posted

技术标签:

【中文标题】从 Delphi 中提取 TWebBrowser 中的 iframe 内容【英文标题】:Extract iframe content in TWebBrowser from Delphi 【发布时间】:2021-04-01 02:46:27 【问题描述】:

我有一个 TWebBrowser 组件,我加载了一个丰富的文本编辑器的 URL。编辑后,我想检索文本的 html(及其所有标记)。

用浏览器调试器看一下,我可以看到编辑器将文本存储在 iframe 中:

我可以通过以下方式获取 iframe:

  NodeName := 'htmleditor_ifr';
  BodyIframe := (WebBrowser1.Document as IHTMLDocument3 ).getElementById(NodeName);

但我不知道如何检索内部文档。

有什么建议吗?

【问题讨论】:

contentDocument @Olivier 我看到你的答案是 javascript,我正在使用 Delphi。 我的答案是你正在使用的 DOM。 getElementById() 也是 DOM,以防你不知道。 Delphi 有 getElementById 方法,但没有 contentDocument 方法,所以很遗憾,我不能使用这种方法。 尝试将返回的元素转换为IHTMLIFrameElement3 ,然后您将能够访问contentDocument 属性。 【参考方案1】:

这是我对 Delphi 7 的解决方案。

我的 Delphi 版本不包含 IHTMLIFrameElement3 的实现,但 IDE 提供了一种将其添加到您的项目的方法:

菜单组件 > 导入 ActiveX 控件

通过此对话框,您可以生成一个新单元,其中包含 Delphi 7 安装中缺少的所有定义:

  CLASS_HTMLFrameElement: TGUID = '3050F314-98B5-11CF-BB82-00AA00BDCE0B';
  IID_IHTMLIFrameElement: TGUID = '3050F315-98B5-11CF-BB82-00AA00BDCE0B';
  IID_IHTMLIFrameElement2: TGUID = '3050F4E6-98B5-11CF-BB82-00AA00BDCE0B';
  IID_IHTMLIFrameElement3: TGUID = '30510433-98B5-11CF-BB82-00AA00BDCE0B';
  DIID_DispHTMLIFrame: TGUID = '3050F51B-98B5-11CF-BB82-00AA00BDCE0B';
  CLASS_HTMLIFrame: TGUID = '3050F316-98B5-11CF-BB82-00AA00BDCE0B';

[...]

// *********************************************************************//
// Interface: IHTMLIFrameElement3
// Flags:     (4416) Dual OleAutomation Dispatchable
// GUID:      30510433-98B5-11CF-BB82-00AA00BDCE0B
// *********************************************************************//
  IHTMLIFrameElement3 = interface(IDispatch)
    ['30510433-98B5-11CF-BB82-00AA00BDCE0B']
    function Get_contentDocument: IDispatch; safecall;
    procedure Set_src(const p: WideString); safecall;
    function Get_src: WideString; safecall;
    procedure Set_longDesc(const p: WideString); safecall;
    function Get_longDesc: WideString; safecall;
    procedure Set_frameBorder(const p: WideString); safecall;
    function Get_frameBorder: WideString; safecall;
    property contentDocument: IDispatch read Get_contentDocument;
    property src: WideString read Get_src write Set_src;
    property longDesc: WideString read Get_longDesc write Set_longDesc;
    property frameBorder: WideString read Get_frameBorder write Set_frameBorder;
  end;

// *********************************************************************//
// DispIntf:  IHTMLIFrameElement3Disp
// Flags:     (4416) Dual OleAutomation Dispatchable
// GUID:      30510433-98B5-11CF-BB82-00AA00BDCE0B
// *********************************************************************//
  IHTMLIFrameElement3Disp = dispinterface
    ['30510433-98B5-11CF-BB82-00AA00BDCE0B']
    property contentDocument: IDispatch readonly dispid -2147413992;
    property src: WideString dispid -2147413991;
    property longDesc: WideString dispid -2147413990;
    property frameBorder: WideString dispid -2147413989;
  end;

// *********************************************************************//
// DispIntf:  DispHTMLIFrame
// Flags:     (4112) Hidden Dispatchable
// GUID:      3050F51B-98B5-11CF-BB82-00AA00BDCE0B
// *********************************************************************//
  DispHTMLIFrame = dispinterface
    ['3050F51B-98B5-11CF-BB82-00AA00BDCE0B']
    procedure setAttribute(const strAttributeName: WideString; AttributeValue: OleVariant;
                           lFlags: Integer); dispid -2147417611;
    function getAttribute(const strAttributeName: WideString; lFlags: Integer): OleVariant; dispid -2147417610;
    function removeAttribute(const strAttributeName: WideString; lFlags: Integer): WordBool; dispid -2147417609;
    property _className: WideString dispid -2147417111;
    property id: WideString dispid -2147417110;
    property tagName: WideString readonly dispid -2147417108;

 // more

有了这个,我遵循了@Olivier 的提示:

  NodeName := 'htmleditor_ifr';
  BodyIframe := (WebBrowser1.Document as IHTMLDocument3 ).getElementById(NodeName);
  ContentHTML := (((BodyIframe as IHTMLIFrameElement3 ).contentDocument) as IHTMLDocument2 );
  Body := ContentHTML.body.innerHTML;

【讨论】:

以上是关于从 Delphi 中提取 TWebBrowser 中的 iframe 内容的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Delphi 10.3.3 中访问 TWebBrowser.Document 时克服内存泄漏

使用delphi在Android下的TWebbrowser中全屏观看youtube或其他视频时出现问题

Delphi:在 TWebBrowser 中显示 PDF

Delphi 中TWebBrowser的扩展控件TExWebBrowser

Delphi TWebBrowser JavaScript 错误和 Cookie

Delphi TWebBrowser[6] 获取网页所有链接(元素)