将网页解析成dom树的几种方法

来源:互联网 发布:普通话发音训练软件 编辑:程序博客网 时间:2024/05/23 10:35

当需要将一个网页解析成比较直观的dom树形式,有以下几种方法。

(1)MSHTML中提供的IWebBrowser2接口。输入为网页的url;

IHTMLDocument2 *pDoc = NULL;
 
 CoInitialize(NULL);

 //取得网页内容
  IWebBrowser2* pWebBrowser = NULL;
    HRESULT hr = CoCreateInstance(CLSID_InternetExplorer,NULL,CLSCTX_LOCAL_SERVER,IID_IWebBrowser2,(void**)&pWebBrowser );
 
 if( FAILED(hr) )
 {
  MessageBox(NULL,_T("WebBrowser2接口失败"),_T("Error"),NULL);
  return -1 ;
 }
 
 string WebUrl("http://beiningsa.blog.sohu.com/130372778.html");
 CComVariant varUrl( WebUrl.c_str() );
    CComVariant var;
 
    hr = pWebBrowser->Navigate2( &varUrl,&var,&var,&var,&var );
 if( FAILED(hr) ) return -1;

     READYSTATE readystate; 
 hr = pWebBrowser->get_ReadyState(&readystate);
 if( FAILED( hr ) ) return -1;
 
 DWORD t1 = GetTickCount();
 while( READYSTATE_COMPLETE != readystate )
 {
  Sleep(50);
        pWebBrowser->get_ReadyState(&readystate);
 }
    DWORD t2 = GetTickCount()-t1;
 std::cout<<"网页下载时间:"<<t2<<endl;

 CComPtr<IDispatch>pDisp;
 pWebBrowser->get_Document( &pDisp );
    CComQIPtr< IHTMLDocument2 >pDoc2( pDisp );

 CComQIPtr< IHTMLElement >pBody;
    pDoc2->get_body( &pBody );

 

 

(2)借助MSHTML中的IHTMLDocument2中的write方法,输入为网页源码字符串;

 

Coinitialize(NULL);

IWebBrowser2* pWeb2 = NULL;
  HRESULT hr = CoCreateInstance( CLSID_InternetExplorer,NULL,CLSCTX_LOCAL_SERVER,IID_IWebBrowser2,(void**)&pWeb2 );
   CComQIPtr< IHTMLDocument2 >pDoc2;
  if( pWeb2 )
  {
   CComVariant var( "about:blank" );
   CComVariant vEmpty;
   HRESULT hr = pWeb2->Navigate2( &var,&vEmpty,&vEmpty,&vEmpty,&vEmpty );
   CComPtr< IDispatch >pDisp;
   pWeb2->get_Document( &pDisp );
   pDoc2 = pDisp;
   pDisp.Detach()->Release();
   }

  if(pDoc2 )
 {
  WriteDebugLog( 2,"InitDomTree","开始执行");
  SAFEARRAY* psa = SafeArrayCreateVector( VT_VARIANT, 0, 1 );
  VARIANT *param = NULL;
  CComBSTR bsData = CComBSTR( m_strCode.c_str() );
  HRESULT hr = SafeArrayAccessData( psa, (LPVOID*)&param );
  param->vt = VT_BSTR;
  param->bstrVal = bsData.Copy();

  pDoc2->write( psa );//取到document2接口指针,解析源码;
  pDoc2->close();

  SafeArrayUnaccessData( psa );
  SafeArrayDestroyData( psa );
    
  CComQIPtr< IHTMLElement >pBody;
  pDoc2->get_body( &pBody );

}

 

(3)使用IMarkservice中的parsestring,据jiangsheng说有内存泄露,是这个接口的一个bug,官方以发布报告,解决方法为第二种方法。

if( SUCCEEDED( CoInitialize( NULL ) ) )
  {
   
   CComPtr< IHTMLDocument2 >pDoc ;
   HRESULT hr = CoCreateInstance( CLSID_HTMLDocument,NULL,CLSCTX_INPROC_SERVER, IID_IHTMLDocument2,reinterpret_cast<LPVOID *>( &pDoc ) );
   DWORD t3 = 0;
   if (pDoc)
   {
    CComQIPtr< IPersistStreamInit >pPersist;   
    pDoc->QueryInterface( IID_IPersistStreamInit,  reinterpret_cast <LPVOID*>(&pPersist) );
    
    if (pPersist)
    {
     pPersist->InitNew();
     pPersist.Release();
     
     CComPtr< IMarkupServices > pMS;
     pDoc->QueryInterface(IID_IMarkupServices, reinterpret_cast<LPVOID *>( &pMS) );
     
     if (pMS)
     {
      
      CComPtr< IMarkupContainer >pMC;
      CComPtr< IMarkupPointer >pMkStart;
      CComPtr< IMarkupPointer >pMkFinish;
      
      pMS->CreateMarkupPointer(&pMkStart);
      pMS->CreateMarkupPointer(&pMkFinish);
      
      HRESULT hr0 = pMS->ParseString(szHTML,0,&pMC,pMkStart, pMkFinish );
      szHTML.Empty();
      
      CComBSTR bvret;
      pDoc->get_readyState( &bvret );
      if( bvret )
       hFile<< (char*)(_bstr_t)bvret;
      
      if (pMC)
      {
       CComPtr<IHTMLDocument2>pNewDoc = NULL; 
       pMC->QueryInterface( IID_IHTMLDocument2,reinterpret_cast<LPVOID *>( &pNewDoc ));
       if( pNewDoc )
       {
        pNewDoc.Release();
       }
       pMC.Release();
      }
      pMS.Release();
     }
     
    }
    pDoc.Release();
   }
   ::CoUninitialize();
  }

 

(4)借助tidy库解析。

 参考HTML Tidy的官方网站:http://tidy.sourceforge.net/docs/api/ 

不多说了。

 

 

第一种方法,WebBrowser控件会将所有的页面元素全部下载下来,比较慢,若没有下载完,相关的UI属性不是最后网页所展现的样式;

这种方法,解析网页很慢,但是分析网页非常详尽;

 

第二种方法比第一种方法快,而且也可以取到UI属性;不同的是,源码下载这一块可以自己单独控制,但是,对于有iframe框架的网页,推荐用第一种方法来解析;

 

第三种方法解析后的dom树没有ui属性;但是解析速度非常快;只是需要操作单独的元素,也就够了,但是,有内存泄漏,要求不很严格的情况下,可以使用下。

 

第四种性能同第三种;详细见网站;

原创粉丝点击