首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

C++ 利用COM接口操作网页元素的有关问题

2012-09-27 
C++ 利用COM接口操作网页元素的问题前两日,写一个遍历网页元素的代码,遇到问题,不得解、、、、、实现代码所遍历

C++ 利用COM接口操作网页元素的问题
前两日,写一个遍历网页元素的代码,遇到问题,不得解、、、、、
  
  实现代码所遍历的网页是直接遍历IE实例个数来完成。即利用 CComPtr< IShellWindow >。也就是说,假设须要遍历的网页记为网页 A。则网页A是通过浏览器方式打开的,而并非程序所用控件打开。

  通过CComPtr< IShellWindow >, 得到了网页A的 CComPtr< IWebBrowser >、、、
  再通过CComPtr< IWebBrowser >,得到了一个 IDispatch,再通过其得到 CComQIPtr< IHTMLDocument2 >;
  至此,已得到指向A页面的IHTMLDocument2 的指针。通过其 get_title( &BSTR ),可以正常得到网页A的标题、、、

  问题如下:
  第一次的做法:
  当我遍历IHTMLDocument2时,
  使用 IHTMLDocument2 的 get_length( &long ),得到其 IHTMLFramesCollection2集合个数。 发现值是 3;
  在调用IHTMLFramesCollection2 的方法 item( iNdex, ( void ** )IHTMLWindow2 ), 循环 3 次,可正常得到3个指向
  IHTMLWindow2的指针( 准确来说是非0值,值看起来似乎正常 )。
  每次当我再调用IHTMLWindow2的 get_document( IHTMLDocument2 ),欲获得相对应的IHTMLDocument2的指针时,三次均得到一个空指针、、、、、、、
   
  后来,尝试如下:
  第一次得到IHTMLDocument2 的指针时,便不对它进行遍历,直接调用 elementFromPoint( long x, long y, IHTMLElement ); 而 x , y ,均以零开始,扫描从坐标 (0,0) 一直到 (3000, 5000),x 以 +10递增,y 以加2递增。
可得到的IHTMLElement, 再调用其tagName方法,显示发现,每次循环调用得到的标签元素似乎总是 HTML、DIV、IFRAME、H、A等之类的,但对于 Input、Form 之类的却得不到、、、(当然,我确定页面上是存在诸多类似标签的)所以,有点不解elementFromPoint的用法,是不是它只能得到HTML、DIV等之类的标签?我用这个函数时,知道它可能登不了台的,但还是试了下、、、、、、
  我继续用第一次得到的IHTMLDocument2的指针, 调用get_cookie( &BSTR ),可以正常得到该页面的COOKIE;
  但如果遍历网页B时,得到其IHTMLFramesCollection2的个数是2,,该代码却能正常遍历出所有Input元素、、、
  于是,我迷忽了、、、、、
  我在想这个问题:
  网页A,它的Frames 为 3。一个页面,它引入了3个其它独立页面,如网页头是单独的,网页正文内容,再加上网页底部的版权信息,而Input之类的元素都在正文的页面当中,所以,遍历不出来
  而网页B,它的Frames 为2,它引入了两个独立页面,正文 和 网页底部信息。此时,Input的元素均在 正文部分,所以,可以正常遍历出Input元素、、、、、
  不知道我有没有说明白,也不知道有没有办法可以解决一个问题:只要一个网页A,在浏览器内可以显示出来的Input元素,我们都可以操作它??不管它网页是使用了什么样的技术。
  或是,网页开发过程中,有木有一种技术可以屏蔽其它软件得到其Input元素???(因为网页A应该有安全机制的,你懂的)-------这个问题最重要、、、、、
   

  比如,我帖个Google的网址: http://www.google.com.hk/ig?hl=zh-CN&source=webhp&refresh=1
  在上面这个网页中,填入搜索关键字的那个Input元素可以正常得到,但是,该页面下面引用的一些模块的元素就无法得到了。下面将代码贴下,当然,假设我知道遍历元素的类型不同获得方法也不同 如Select元素、input 、、、

   




#include "GetElement.h"
#include <iostream>
using namespace std;

BOOL TraversalDocument( CComQIPtr< IHTMLDocument2 > pDoc2 ); 

int main()
{
  //SHDocVw:IShellWindowsPtr m_sp;
  ::CoInitialize( NULL );
  CComPtr< IShellWindows > pShellWin;
  CComPtr< IDispatch > pDispatch;
  CComQIPtr< IWebBrowser2 > pWebBro;
  CComQIPtr< IHTMLDocument2 > pDoc2;
   

  HRESULT hr = pShellWin.CoCreateInstance( CLSID_ShellWindows );
  if ( FAILED( hr ) )
  {
  cout << "IShellWindows CoCreateInstance Error" << endl;
  goto _MainExit;
  }


  long lInstanceCount = 0;
  pShellWin->get_Count( &lInstanceCount );
  for ( long lIndex = 0; lIndex < lInstanceCount; lIndex++ )
  {
  pDispatch.Release();
  hr = pShellWin->Item( CComVariant( lIndex ), &pDispatch );
  if ( FAILED( hr ) )
  {
  continue;
  }

  pWebBro.Release();
  pWebBro = pDispatch;
  if ( !pWebBro )
  {
  continue;
  }

  pDispatch.Release();
  hr = pWebBro->get_Document( &pDispatch );
  if ( FAILED( hr ) )
  {
  continue;
  }

  pDoc2.Release();
  pDoc2 = pDispatch;
  if ( !pDoc2 )
  {


  continue;
  }

  TraversalDocument( pDoc2 );

  }


_MainExit:
   
  // ::CoUninitialize();
  system( "pause" );
  return 0;
}

BOOL TraversalDocument( CComQIPtr< IHTMLDocument2 > pDoc2 )
{
  CComQIPtr< IHTMLFramesCollection2 > pFramCol2;
   
  pFramCol2.Release();
  HRESULT hr = pDoc2->get_frames( &pFramCol2 );
  if ( FAILED( hr ) )
  {
  return FALSE;
  }

  long lFramCount = 0;
  hr = pFramCol2->get_length( &lFramCount );
  if ( FAILED( hr ) )
  {
  return 0;
  }
   
  if ( lFramCount )
  {
  CComQIPtr< IHTMLDocument2 > pTraDoc2;
  CComQIPtr< IHTMLWindow2 > pWin2;
  VARIANT varIndex;
  VARIANT varDisp;
  varIndex.vt = VT_I4;
  varDisp.vt = VT_DISPATCH;
  for ( int iIndex = 0; iIndex < lFramCount; iIndex++ )
  {
  varIndex.intVal = iIndex;
  varDisp.pdispVal = NULL;
  hr = pFramCol2->item( &varIndex, &varDisp );
  if ( FAILED( hr ) )
  {
  continue;
  }

  pWin2.Release();
  pWin2 = varDisp.pdispVal;
  pTraDoc2.Release();
  hr = pWin2->get_document( &pTraDoc2 );
  if ( FAILED( hr ) )
  {
  continue;
  }

  TraversalDocument( pTraDoc2 );
  }
  }
   
  CComQIPtr< IHTMLElementCollection > pEleColl;
  pEleColl.Release();
  hr = pDoc2->get_forms( &pEleColl );
  if ( FAILED( hr ) )
  {
  return FALSE;
  }

  CComQIPtr< IHTMLFormElement > pFormEle;
  long lFormCount = 0;
  hr = pEleColl->get_length( &lFormCount );
  if ( FAILED( hr ) )
  {
  return FALSE;
  }

  CComPtr< IDispatch > pDis;
  CComQIPtr< IHTMLInputElement > pInput;
  VARIANT varName;
  varName.vt = VT_BSTR;
  varName.bstrVal = NULL;
  VARIANT varIndex;
  varIndex.vt = VT_I4;
  BSTR bsStr;
  char* lpszText2;
  for ( long lFormIndex = 0; lFormIndex < lFormCount; lFormIndex++ )
  {
  pDis.Release();
  hr = pEleColl->item( CComVariant( lFormIndex ), CComVariant(), &pDis );
  if ( FAILED( hr ) )
  {
  continue;
  }

  pFormEle.Release();
  pFormEle = pDis;
  if ( !pFormEle )
  {
  continue;
  }

  long lEleCount = 0;
  hr = pFormEle->get_length( &lEleCount );
  if ( FAILED( hr ) )
  {
  continue;
  }
  for ( long lEleIndex = 0; lEleIndex < lEleCount; lEleIndex++ )
  {
CComDispatchDriver spInputElement;
hr = pFormEle->item( CComVariant( lEleIndex ), CComVariant(), &spInputElement );
if ( FAILED( hr ) )continue;

CComVariant vName,vVal,vType;
hr = spInputElement.GetPropertyByName( L"name", &vName );


if( FAILED( hr ) )continue;
hr = spInputElement.GetPropertyByName( L"value", &vVal );
if( FAILED( hr ) )continue;
hr = spInputElement.GetPropertyByName( L"type", &vType );
if( FAILED( hr ) )continue;
   
  if ( vName.bstrVal != NULL )
  {
  lpszText2 = _com_util::ConvertBSTRToString(vName.bstrVal);
  cout<< "Name:" << lpszText2;  
  }
  if ( vVal.bstrVal != NULL )
  {
  lpszText2 = _com_util::ConvertBSTRToString(vVal.bstrVal);
  cout<< " Value:" << lpszText2;  
  }
  if ( vType.bstrVal != NULL )
  {
  lpszText2 = _com_util::ConvertBSTRToString(vType.bstrVal);
  cout<< " Type:" << lpszText2 << endl;  
  }
  }
   
  }  

  return FALSE;
}

 

[解决办法]
如果只取html中的值,com过于复杂,过于难用。 

可以搜索一些开源的库
[解决办法]

探讨

现在的问题是、、、、、在C++中,如何通过IFrame来得到其Document2 的一个指针呢、、、、、、、

热点排行