【问题标题】:Obtaining visible text on a page from an IHTMLDocument2*从 IHTMLDocument2* 获取页面上的可见文本
【发布时间】:2012-04-06 06:06:11
【问题描述】:

我正在尝试获取 Internet Explorer Web 浏览器窗口的文本内容。

我正在执行以下步骤:

  1. 获得指向 IHTMLDocument2 的指针
  2. 我从 IHTMLDocument2 获取正文作为 IHTMLElement
    3. 在正文上我调用 get_innerText

编辑


  1. 我获取了 body 的所有子元素并尝试对所有 IHTMLElements 进行递归调用
  2. 如果我得到任何不可见的元素,或者如果我得到一个标签为脚本的元素,我会忽略该元素及其所有子元素。

我的问题是

  1. 除了页面上可见的文本之外,我还获得了具有 style="display: none" 的内容
  2. 对于 google.com,我还获得了 javascript 以及文本。

我尝试了递归方法,但我不知道如何处理这样的场景,

<div>
Hello World 1
<div style="display: none">Hello world 2</div>
</div>

在这种情况下,我将无法获得“Hello World 1”

谁能帮我找出从 IHTMLDocument2* 获取文本的最佳方法。 我使用的是 C++ Win32,没有 MFC,ATL。

谢谢, 阿什。

【问题讨论】:

  • 您可能需要迭代(从最后一个到第一个)IHTMLDocument2 元素,并删除不需要的节点。
  • @kobik 我已经考虑过这种方法,但有时父元素可能包含可能未包含在任何 html 标记中的文本。举个例子。 &lt;div&gt;Hello World 1&lt;div&gt;Hello World 2&lt;/div&gt;&lt;/div&gt; 如果我遵循这种方法,我将无法获得 Hello World 1。

标签: c++ winapi html-parsing ole mshtml


【解决方案1】:

如果您在 document.body.all 元素上向后迭代,您将始终从内向外遍历元素。所以你不需要自己走递归。 DOM 会为你做这件事。例如(代码在 Delphi 中):

procedure Test();
var
  document, el: OleVariant;
  i: Integer;
begin
  document := CreateComObject(CLASS_HTMLDocument) as IDispatch;
  document.open;
  document.write('<div>Hello World 1<div style="display: none">Hello world 2<div>This DIV is also invisible</div></div></div>');
  document.close;
  for i := document.body.all.length - 1 downto 0 do // iterate backwards
  begin
    el := document.body.all.item(i);
    // filter the elements
    if (el.style.display = 'none') then
    begin
      el.removeNode(true);
    end;
  end;
  ShowMessage(document.body.innerText);
end;

旁注: 至于您使用递归方法的场景:

<div>Hello World 1<div style="display: none">Hello world 2</div></div>

如果例如我们的元素是第一个 DIV,el.getAdjacentText('afterBegin') 将返回 "Hello World 1"。所以我们可能可以在元素上向前迭代并收集getAdjacentText('afterBegin'),但这有点困难,因为我们需要为el.currentStyle.display测试每个元素的父元素。

【讨论】:

  • 在我的情况下,我正在处理一个已经打开的 IE 实例,因此是否建议我获取正文的外部 HTML,并将其写入一些 IHTMLDocument,就像您在示例中所做的那样,然后操作它的 DOM?
  • 是的,因为这样你就不会改变打开的IE实例的DOM,你可以随意解析和滥用它。
  • 谢谢!我能够将它映射到 C++,我想我已经让它工作了。我也想知道向后迭代的意义。
  • 我们向后迭代,因为如果我们向前迭代并有例如3 个嵌套元素并删除元素索引 1(第二个元素),索引 2 处的子元素也将被删除。所以当循环索引达到 2 时,body.all.item(2) 被移除,并且会引发异常。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-11-23
  • 2021-04-08
  • 1970-01-01
  • 2011-12-18
  • 2013-07-25
  • 1970-01-01
相关资源
最近更新 更多