<source id="4vppl"><ins id="4vppl"></ins></source>
<u id="4vppl"><sub id="4vppl"><label id="4vppl"></label></sub></u>
<object id="4vppl"></object>
  • <u id="4vppl"><li id="4vppl"><label id="4vppl"></label></li></u>

    <object id="4vppl"></object>
    <b id="4vppl"><sub id="4vppl"><tr id="4vppl"></tr></sub></b>

      <i id="4vppl"><thead id="4vppl"></thead></i>

      <thead id="4vppl"><li id="4vppl"><label id="4vppl"></label></li></thead>

      當前位置:首頁 > 網站舊欄目 > 學習園地 > 程序開發教程 > IHTMLDocument2接口訪問Dom,完成自動搜索

      IHTMLDocument2接口訪問Dom,完成自動搜索
      2009-12-23 10:57:24  作者:cnblogs  來源:cnblogs

      首先感嘆下:冬至了,別人都去聚餐言歡,我去孤獨寫這些文字

       之所以寫這個東西,是一個網管朋友出50元大洋讓我寫的,有了這個東東,在網吧可以很輕松的做網吧增值廣告了.當時是星期天,想著又沒有事做,就答應了,雖知星期天的事情還真多,知道昨天晚上才搞定.

       我們來看下這位朋友的要求:

      1、網站址:http://www.v232.com/?username,后面的username最好能在配置文件中配置。

      2、打開軟件后搜索一次(搜索關鍵詞最好從我那網站調用,因為我那網站的關鍵字是隨機網絡熱門關鍵字地址是http://61.187.248.172:8099/listc.do這個地址最好也能配置,因為有時會變)
      3、搜索一次后還必須要點擊一次搜索到的結果,不然會視為無效搜索。
      4、等上幾秒(最好可以通過配置文件配置)再運行一次搜索即可,當然最好能讓他運行三次,運行三次后還是等上幾十分鐘(最好能配置)再運行。
      5、全后臺運行,不能移動改變鼠標位置。

       

      一條條分析下:

      第一個要求,too easy ,編程花費時間可以忽略不計,用ini文件,用GetPrivateProfile**的api搞定

      第二個要求:分兩步,

                (1)獲取關鍵字,CInternetSession + CHttpFile后再截取字符串搞定(當然換了地址,代碼換了就不行了)

                (2)搜索一次,這個一次搜索,過程也是比較難搞的,大家可以打開那個http://www.v232.com/?username這個網站其實用搜狗的廣告聯盟,過程挺簡單的,給搜索框填寫關鍵字,然后單擊搜索按鈕,這里起初我想的也是很簡單的,可是問題確實不斷的出來,不過最終都解決了,要不我也不敢在這些這些字了,呵呵

               這個過程要用本文的主角IHMLDocument2了,而且還用到了跨域訪問,可以看那個網站,是把搜狗網站用iframe引進來了,兩個document屬于不同的域,訪問就不便了,這個接口竟然也有這種限制.不過不用怕,網頁都到自己的電腦上了,自己的電腦,難道還不聽自己的話么.如果真是這樣我寧愿把電腦砸了.

      第三個要求:沒什么了,第二個要求中的差不多,其實應該還簡單的,因為搜索結果是一個框架的,而且又沒有跨域的問題.不過唯一不好的就是搜索結果的鏈接默認是在新窗口打開的,這樣的話,這個軟件就不能夠足夠的隱藏了,因為會打開一個新的瀏覽器窗口了,解決辦法,就是在當前打開了,所以更改鏈接的target屬性.

      第四個要求:用SetTimer搞定即可.

      第五個要求:沒什么了,隱藏對話框窗口.

      先搞個圖片:

      下面就開始主演登場了

       

      首先盜用別人的一張圖來展示下網頁的結構

       

      [page]
      我用的是VS2008中的activeX Microsoft web browser控件所以可以很容易獲取到IHTMLDocument2對象

      m_ie是與activeX Microsoft web browser控件關聯的變量,CComPtr是Com了,可以實現智能指針

      代碼
      CComPtr<IDispatch> spDispDoc = m_ie.get_Document();
          CComPtr
      <IHTMLDocument2> spHtmlDoc = NULL;
          hr 
      = spDispDoc->QueryInterface(IID_IHTMLDocument2,(void **)&spHtmlDoc);
          
      if (FAILED(hr) || NULL == spHtmlDoc)
          {
              
      //return FALSE;
          }

       

       

      上面在分析中說了要第二個要求中,有框架的,還要跨域的,可以看上圖,我們知道對已訪問框架網頁的IHtmlDocument2,我們需要要獲取Frame對象,然后是Window對象,然后再次才是框架網頁的IHTMLDocument2對象.

      所以就按此順序來了

       

      代碼
          spHtmlDoc->get_readyState(&state); 
              pSate 
      = _com_util::ConvertBSTRToString(state);
              
      if(strcmp(pSate,"complete")==0//檢測下狀態
              {
                  
              }
              
      else
              {
                  
      return;
              }
              
      //開始解析網頁
              CComPtr<IHTMLWindow2>  pHTMLWnd = NULL;   
              CComPtr
      <IHTMLDocument2> pChilDoc = NULL;
              LPDISPATCH   lpDispatch;   

              
              CComPtr
      <IHTMLFramesCollection2> pFrames=NULL;
              spHtmlDoc
      ->get_frames(&pFrames);
              
      long frameCount = 0;
              pFrames
      ->get_length(&frameCount);
              
      //獲取第一個frame
              VARIANT   varindex,varresult;  
              varresult.vt
      =VT_DISPATCH;   
              varindex.vt   
      =   VT_I4;
              
              varindex.lVal 
      = 0;
              hr 
      = pFrames->item(&varindex,   &varresult);
              
      if (S_OK != hr)
              {
                  
      return;
              }

              lpDispatch 
      = (LPDISPATCH)varresult.ppdispVal;//為了跨域訪問
              if(SUCCEEDED(lpDispatch->QueryInterface(IID_IHTMLWindow2,   (LPVOID   *)&pHTMLWnd)))   
              {   
                   pChilDoc 
      = HtmlWindowToHtmlDocument(pHTMLWnd); //為了跨域訪問,此函數突破跨域限制
                   if (pChilDoc==NULL)
                   {
                       
      return;
                   }
              }
              
      else
              {
                  
      return;
              }

       

      做這些訪問操作,需要多加判斷,或者用try catch了.

      主要是這個IDispatch,剛才我也弄得頭暈了,后來就明白了,可以把這個看成對封裝一大堆元素東西的結構,就像我們訪問Document中的元素,一次得到都是封裝的,這個IDsipach可以返回我們想要的,記得用get_all,get_frames,get_forms等返回的都是一塊東西,我們沒有辦法直接訪問,然后有一個專門拆包的人,我們說要個input元素,然后這個人就到包里找,找到了就給我們,找不到了,就不進行操作了.就像我高中學校里的傳達室一樣,每次都有很多郵件在一個箱子里,我沒有權利去檢查里面有沒有我或者我同學的信,我每次都得問那老爺爺有沒有"誰誰誰"的信,老爺爺在里面找半天,有了就給我,沒了,也不理我,繼續給其他同學找信.

      傳達室就像一個Document對象,而箱子就是一些元素的集合,老爺爺就是IDispatch了,信和郵件就是我們要的網頁元素了,像a input table等.

      上面的代碼中有突破跨域的,其實也是很實用的,這個傳達室沒有我的郵件,我得到另一個找找看了,不能吊死到一棵樹上呀

      上面用到得HtmlWindowToHtmlDocument函數是從MSDN的forum上找到得,經過我稍微的改版,改成適合我當前工程的函數,下面貼出來了

       

      代碼
      CComPtr<IWebBrowser2> CTimerSerachDlg::HtmlWindowToHtmlWebBrowser(CComPtr<IHTMLWindow2> spWindow)
      {     
          ATLASSERT(spWindow 
      != NULL);     
          CComQIPtr
      <IServiceProvider>  spServiceProvider = spWindow;     
          
      if (spServiceProvider == NULL)     
          {          
              
      return CComPtr<IWebBrowser2>();     
          }     
          CComPtr
      <IWebBrowser2> spWebBrws;     
          HRESULT hRes 
      = spServiceProvider->QueryService(IID_IWebBrowserApp, IID_IWebBrowser2, (void**)&spWebBrws);     
          
      if (hRes != S_OK)     
          {          
              
      return CComPtr<IWebBrowser2>();     
          }     
          
      return spWebBrws;
      }

      // Converts a IHTMLWindow2 object to a IHTMLDocument2. Returns NULL in case of failure.
      // It takes into account accessing the DOM across frames loaded from different domains.
      CComPtr<IHTMLDocument2> CTimerSerachDlg::HtmlWindowToHtmlDocument(CComPtr<IHTMLWindow2> spWindow)
      {     
          ATLASSERT(spWindow 
      != NULL);     
          CComPtr
      <IHTMLDocument2> spDocument;     
          HRESULT hRes 
      = spWindow->get_document(&spDocument);         
          
      if ((S_OK == hRes) && (spDocument != NULL))     
          {          
              
      // The html document was properly retrieved.          
              return spDocument;     
          }     
          
      // hRes could be E_ACCESSDENIED that means a security restriction that     
          
      // prevents scripting across frames that loads documents from different internet domains.     
          CComPtr<IWebBrowser2>  spBrws = HtmlWindowToHtmlWebBrowser(spWindow);     
          
      if (spBrws == NULL)     
          {         
              
      return CComPtr<IHTMLDocument2>();     
          }     
          
      // Get the document object from the IWebBrowser2 object.     
          CComPtr<IDispatch> spDisp;     hRes = spBrws->get_Document(&spDisp);    
          spDocument 
      = spDisp;     
          
      return spDocument;
      }

       

      英文注釋都保留了,原理就是同window來獲取Document對象了,我早說了,自己的電腦能不聽自己的話么.即使不聽,也得教訓下,讓它聽話.

      其實上面基本就是核心代碼了,這里需要注意的就是VARIANT 和BSTR類型變量的使用,這個網上的資料還是很多的,我看網上的資料沒看明白,看msdn明白了.

      VARIANT 就是一個為了實現語言無關性,Com接口中的.用的時候,就是指定下當前的數據類型,然后往指定的數據類型的屬性中賦值就可以了,是一個封裝了大多數基本數據類型的類.

       

      還有一個難點就是,到了搜索結果頁,直接用IHTMLLinkElement2 和IHTMLLinkElement都得不到A的鏈接,無奈了,用IHTMElement2 IHTMElement 都可以了的,起初直接用IHTMLLinkElement2強制轉換IHTMElement2 ,然后修改鏈接的target(IHTMLLinkElement2才有的)屬性,不行,肯定不行了,向下類的繼承也知道不行的.這折騰了我好長時間.就又到msdn看呀看,終于看了到了IHTMLElement 的SetAttribute、RemoveAttribute,頓感救星來了,果然如此,用SetAttribute("target","_self");當然里面的字符串要用BSTR了,到此就完成了,中間隔時間,我全部用SetTimer來完成,下面貼出OnTimer的代碼(我調試的代碼都在,有的代碼是沒有用的了)

       

      代碼
      void CTimerSerachDlg::OnTimer(UINT_PTR nIDEvent)
      {
          
      // TODO: 在此添加消息處理程序代碼和/或調用默認值
          BSTR state = {0};
          
      char *pSate=NULL;
          
          
      if (nIDEvent==1)
          {
              GetKeyWord();
              HRESULT hr 
      = E_FAIL;
              CComPtr
      <IDispatch> spDispDoc = m_ie.get_Document();
              CComPtr
      <IHTMLDocument2> spHtmlDoc = NULL;
              hr 
      = spDispDoc->QueryInterface(IID_IHTMLDocument2,(void **)&spHtmlDoc);
              
      if (FAILED(hr) || NULL == spHtmlDoc)
              {
                  
      //return FALSE;
              }

              spHtmlDoc
      ->get_readyState(&state); 
              pSate 
      = _com_util::ConvertBSTRToString(state);
              
      if(strcmp(pSate,"complete")==0//檢測下狀態
              {
                  
              }
              
      else
              {
                  
      return;
              }
              
      //開始解析網頁
              CComPtr<IHTMLWindow2>  pHTMLWnd = NULL;   
              CComPtr
      <IHTMLDocument2> pChilDoc = NULL;
              LPDISPATCH   lpDispatch;   

              
              CComPtr
      <IHTMLFramesCollection2> pFrames=NULL;
              spHtmlDoc
      ->get_frames(&pFrames);
              
      long frameCount = 0;
              pFrames
      ->get_length(&frameCount);
              
      //獲取第一個frame
              VARIANT   varindex,varresult;  
              varresult.vt
      =VT_DISPATCH;   
              varindex.vt   
      =   VT_I4;
              
              varindex.lVal 
      = 0;
              hr 
      = pFrames->item(&varindex,   &varresult);
              
      if (S_OK != hr)
              {
                  
      return;
              }

              lpDispatch 
      = (LPDISPATCH)varresult.ppdispVal;
              
      if(SUCCEEDED(lpDispatch->QueryInterface(IID_IHTMLWindow2,   (LPVOID   *)&pHTMLWnd)))   
              {   
                   pChilDoc 
      = HtmlWindowToHtmlDocument(pHTMLWnd);
                   
      if (pChilDoc==NULL)
                   {
                       
      return;
                   }
              }
              
      else
              {
                  
      return;
              }
              
              CComPtr
      <IHTMLElementCollection> pForms = NULL;
              pChilDoc
      ->get_forms(&pForms);
              
              
      long formCount = 0;
              pForms
      ->get_length(&formCount);
              CComPtr
      <IDispatch> formDis = NULL;
              _variant_t index 
      = 0;
              hr 
      = pForms->item(index,index,&formDis);
              
              
      if (hr!=S_OK)
              {
                  
      return;
              }
              
      //get the form interface
              CComPtr<IHTMLFormElement> pFirstForm = NULL;
              hr 
      = formDis->QueryInterface(IID_IHTMLFormElement,(void **)&pFirstForm);
              
      if (hr!=S_OK)
              {
                  
      return;
              }
              formDis.Release();
              BSTR formName 
      = {0};
              pFirstForm
      ->get_name(&formName);
              CComPtr
      <IDispatch> inputDis = NULL;
              index 
      = 4;
              pFirstForm
      ->item(index,index,&inputDis);
              CComPtr
      <IHTMLInputTextElement> qElem = NULL;
              inputDis
      ->QueryInterface(IID_IHTMLInputTextElement,(void**)&qElem);
              inputDis.Release();
              BSTR tagName
      ={0};
              BSTR id
      ={0};
              qElem
      ->get_name(&tagName);
              BSTR value 
      = {0};
              
              qElem
      ->put_value(value);
              value
      =m_keyWord.AllocSysString();
              qElem
      ->put_value(value);
              SysFreeString(value); 

              
      //成功后,就不用了
              KillTimer(1);
              SetTimer(
      2,5000,NULL);//開始單擊按鈕
          }
          
      if (nIDEvent==2)
          {
              HRESULT hr 
      = E_FAIL;
              CComPtr
      <IDispatch> spDispDoc = m_ie.get_Document();
              CComPtr
      <IHTMLDocument2> spHtmlDoc = NULL;
              hr 
      = spDispDoc->QueryInterface(IID_IHTMLDocument2,(void **)&spHtmlDoc);
              
      if (FAILED(hr) || NULL == spHtmlDoc)
              {
                  
      //return FALSE;
              }

              spHtmlDoc
      ->get_readyState(&state);
              pSate 
      = _com_util::ConvertBSTRToString(state);
              
      if(strcmp(pSate,"complete")==0)
              {

              }
              
      else
              {
                  
      return;
              }
              
      //開始解析網頁
              CComPtr<IHTMLWindow2>  pHTMLWnd = NULL;   
              CComPtr
      <IHTMLDocument2> pChilDoc = NULL;
              LPDISPATCH   lpDispatch;   


              CComPtr
      <IHTMLFramesCollection2> pFrames=NULL;
              spHtmlDoc
      ->get_frames(&pFrames);
              
      long frameCount = 0;
              pFrames
      ->get_length(&frameCount);
              
      //獲取第一個frame
              VARIANT   varindex,varresult;  
              varresult.vt
      =VT_DISPATCH;   
              varindex.vt   
      =   VT_I4;

              varindex.lVal 
      = 0;
              hr 
      = pFrames->item(&varindex,   &varresult);
              
      if (S_OK != hr)
              {
                  
      return;
              }

              lpDispatch 
      = (LPDISPATCH)varresult.ppdispVal;
              
      if(SUCCEEDED(lpDispatch->QueryInterface(IID_IHTMLWindow2,   (LPVOID   *)&pHTMLWnd)))   
              {   
                  pChilDoc 
      = HtmlWindowToHtmlDocument(pHTMLWnd);
                  
      if (pChilDoc==NULL)
                  {
                      
      return;
                  }
              }
              
      else
              {
                  
      return;
              }

              CComPtr
      <IHTMLElementCollection> pForms = NULL;
              pChilDoc
      ->get_forms(&pForms);

              
      long formCount = 0;
              pForms
      ->get_length(&formCount);
              CComPtr
      <IDispatch> formDis = NULL;
              _variant_t index 
      = 0;
              hr 
      = pForms->item(index,index,&formDis);

              
      if (hr!=S_OK)
              {
                  
      return;
              }
              
      //get the form interface
              CComPtr<IHTMLFormElement> pFirstForm = NULL;
              hr 
      = formDis->QueryInterface(IID_IHTMLFormElement,(void **)&pFirstForm);
              
      if (hr!=S_OK)
              {
                  
      return;
              }
              formDis.Release();
              BSTR formName 
      = {0};
              pFirstForm
      ->get_name(&formName);
              CComPtr
      <IDispatch> inputDis = NULL;
              index 
      = 5;
              pFirstForm
      ->item(index,index,&inputDis);
              CComPtr
      <IHTMLElement> qElem = NULL;
              inputDis
      ->QueryInterface(IID_IHTMLElement,(void**)&qElem);
              inputDis.Release();
              BSTR tagName
      ={0};
              BSTR id
      ={0};
              qElem
      ->get_tagName(&tagName);
              qElem
      ->get_title(&tagName);
              
      /*BSTR value = {0};

              qElem->put_value(value);
              value=m_keyWord.AllocSysString();
              qElem->put_value(value);
              SysFreeString(value); 
      */
              qElem
      ->click();
              
      //成功后,就不用了
              KillTimer(2);
              SetTimer(
      3,5000,NULL);//開始單擊搜索結果
          }
      安徽新華電腦學校專業職業規劃師為你提供更多幫助【在線咨詢
      国产午夜福三级在线播放_亚洲精品成a人片在线观看_亚洲自慰一区二区三区_久久棈精品久久久久久噜噜
      <source id="4vppl"><ins id="4vppl"></ins></source>
      <u id="4vppl"><sub id="4vppl"><label id="4vppl"></label></sub></u>
      <object id="4vppl"></object>
    1. <u id="4vppl"><li id="4vppl"><label id="4vppl"></label></li></u>

      <object id="4vppl"></object>
      <b id="4vppl"><sub id="4vppl"><tr id="4vppl"></tr></sub></b>

        <i id="4vppl"><thead id="4vppl"></thead></i>

        <thead id="4vppl"><li id="4vppl"><label id="4vppl"></label></li></thead>
        亚洲中文字幕手机在线第一页 | 亚洲一区在线国产 | 最新日韩欧美理论在线 | 伊人成伊人成综合网222 | 亚洲视频一区二区在线观看 | 亚洲vs日韩vs欧美vs久久 |