CSDN博客

img skyremember

请问高手怎样才能枚举出网页中所有“输入框”位置(包括IFRAME中),在线等

发表于2008/10/3 11:19:00  1563人阅读

 请问高手怎样才能枚举出网页中所有“输入框”位置(包括IFRAME中),在线等
楼主jinhe1314(hoyoo)2006-05-30 18:43:12 在 VC/MFC / HTML/XML 提问

我用www.codeproject.com上的一个例子,结合vckbase上扬老师的例子实现了这个要求,但是太慢了足足用了15-20秒。请高人指点 问题点数:100、回复次数:12Top

1 楼jiangsheng(蒋晟.Net[MVP])回复于 2006-05-31 01:55:11 得分 50

不要访问IHTMLElementCollection::get_length,用IHTMLElementCollection::get__newEnum  
  void   ListAllLinkUrls(mshtml::HTMLDocument   *myDoc)  
  {  
  mshtml::IHTMLElementCollection   *elementcollection   =  
  dynamic_cast<mshtml::IHTMLElementCollection*>(myDoc->all);  
  if   (elementcollection)   {  
  System::Collections::IEnumerator   *ienum   =  
  elementcollection->GetEnumerator();  
  while   (ienum   &&   ienum->MoveNext())   {  
  mshtml::IHTMLElement   *elem=dynamic_cast<mshtml::IHTMLElement  
  *>(ienum->Current);  
  if   (elem)   {  
  if   (elem->tagName->Equals(S"FRAME"))   {  
  mshtml::HTMLFrameBase   *fb   =   dynamic_cast<mshtml::HTMLFrameBase*>(elem);  
  mshtml::HTMLDocument  
  *myDoc2=dynamic_cast<mshtml::HTMLDocument*>(fb->document);  
  ListAllLinkUrls(myDoc2);  
  }  
  else   if   (elem->tagName->Equals(S"LINK"))   {  
  mshtml::HTMLLinkElement   *le   =  
  dynamic_cast<mshtml::HTMLLinkElement*>(elem);  
  Console::WriteLine("have   link   {0}",le->href);  
  }  
  }  
  }  
  }  
  }   //   ListAllLinkUrlsTop

2 楼lion_wing(凤之焚-业与情的纠缠,死而复生的蜕变!)回复于 2006-05-31 08:50:07 得分 0

自己写过一段,代码复杂,不如这个简单,MARK一下!Top

3 楼jinhe1314(hoyoo)回复于 2006-05-31 10:57:39 得分 0

to   jiangsheng  
  我用你的方法试了一下,分析www.5460.net用了将近6秒,  
  用pIHTMLDocument2->get_frames(   &spFramesCollection2   )和  
  pIHTMLDocument2->get_forms(   &spElementCollection   );  
  遍历用了不到1秒,但是用下面的代码得不出,正确的“IFRAME”中的“输入框”位置(需要吧IFRAME偏移加上才行)  
  pElem->get_offsetHeight(&Height);  
  pElem->get_offsetWidth(&Width);  
  pElem->get_offsetLeft(&Left);  
  pElem->get_offsetTop(&Top);  
  pElem->get_offsetParent(&lpContainer); while   (   lpContainer   )  
  {  
            lpContainer->get_offsetLeft(&lValue);   Left   +=   lValue;  
            lpContainer->get_offsetTop(&lValue);     Top   +=   lValue;  
            lpContainer->get_offsetParent(&lpContainer);  
  }  
  我想问的是怎样由“IHTMLWindow2”得到IFRAME偏移(就是转成IHTMLElement)  
  Top

4 楼lion_wing(凤之焚-业与情的纠缠,死而复生的蜕变!)回复于 2006-05-31 11:21:39 得分 0

用IHTMLFrameBase::get_marginWidth和IHTMLFrameBase::get_marginHeight  
  //mshtml::HTMLFrameBase   *fb   =   dynamic_cast<mshtml::HTMLFrameBase*>(elem);  
  fb->marginWidth(...);  
  fb->marginHeight(...);Top

5 楼jinhe1314(hoyoo)回复于 2006-05-31 11:26:18 得分 0

int   _tmain(int   argc,   TCHAR*   argv[],   TCHAR*   envp[])  
  {  
  ::CoInitialize(NULL); //初始化   COM   公寓  
   
  EnumIE(); //枚举浏览器  
   
  ::CoUninitialize(); //释放   COM   公寓  
   
  cout   <<   _T("======完成======")   <<   endl;  
  getchar(); //等待回车  
   
  return   0;  
  }  
   
  void   EnumIE(   void   )  
  {  
  cout   <<   _T("开始扫描系统中正在运行的浏览器实例")   <<   endl;  
   
  CComPtr<   IShellWindows   >   spShellWin;  
  HRESULT   hr   =   spShellWin.CoCreateInstance(   CLSID_ShellWindows   );  
  if   (   FAILED   (   hr   )   )  
  {  
  cout   <<   _T("获取   IShellWindows   接口错误")   <<   endl;  
  return;  
  }  
   
  long   nCount   =   0; //   取得浏览器实例个数(Explorer   和   IExplorer)  
  spShellWin->get_Count(   &nCount   );  
  if(   0   ==   nCount   )  
  {  
  cout   <<   _T("没有在运行着的浏览器")   <<   endl;  
  return;  
  }  
   
  for(int   i=0;   i<nCount;   i++)  
  {  
  CComPtr<   IDispatch   >   spDispIE;  
  hr=spShellWin->Item(CComVariant(   (long)i   ),   &spDispIE   );  
  if   (   FAILED   (   hr   )   ) continue;  
   
  CComQIPtr<   IWebBrowser2   >   spBrowser   =   spDispIE;  
  if   (   !spBrowser   ) continue;  
   
  CComPtr   <   IDispatch   >   spDispDoc;  
  hr   =   spBrowser->get_Document(   &spDispDoc   );  
  if   (   FAILED   (   hr   )   ) continue;  
   
  CComQIPtr<   IHTMLDocument2   >   spDocument2   =   spDispDoc;  
  if   (   !spDocument2   ) continue;  
   
  //   程序运行到此,已经找到了   IHTMLDocument2   的接口指针  
   
  //   删除下行语句的注释,把浏览器的背景改变看看  
  //   spDocument2->put_bgColor(   CComVariant(   "green"   )   );  
  DWORD   dwStart   =   GetTickCount();  
  EnumForm(   spDocument2   ); //枚举所有的表单  
  DWORD   dwEnd=GetTickCount()   ;  
  DWORD   x=dwEnd-dwStart;  
   
  }  
  }  
   
  void   EnumFrame(   IHTMLDocument2   *   pIHTMLDocument2   )  
  {  
  if   (   !pIHTMLDocument2   ) return;  
   
  HRESULT   hr;  
   
  CComPtr<   IHTMLFramesCollection2   >   spFramesCollection2;  
  pIHTMLDocument2->get_frames(   &spFramesCollection2   ); //取得框架frame的集合  
   
  long   nFrameCount=0; //取得子框架个数  
  hr   =   spFramesCollection2->get_length(   &nFrameCount   );  
  if   (   FAILED   (   hr   )   ||   0   ==   nFrameCount   ) return;  
   
  for(long   i=0;   i<nFrameCount;   i++)  
  {  
  CComVariant   vDispWin2; //取得子框架的自动化接口  
  hr   =   spFramesCollection2->item(   &CComVariant(i),   &vDispWin2   );  
  if   (   FAILED   (   hr   )   ) continue;  
   
  CComQIPtr<   IHTMLWindow2   >   spWin2   =   vDispWin2.pdispVal;  
  CComQIPtr<   IHTMLWindow4   >   spWin4   =   vDispWin2.pdispVal;  
   
  if(   !spWin2   ) continue; //取得子框架的   IHTMLWindow2   接口  
  if(   !spWin4   ) continue;  
  CComQIPtr<   IHTMLFrameBase>   fbase;  
  hr=spWin4->get_frameElement(&fbase);//fbase永远是NULL  
   
  CComPtr   <   IHTMLDocument2   >   spDoc2;  
  spWin2->get_document(   &spDoc2   ); //取得字框架的   IHTMLDocument2   接口  
   
   
  EnumForm(   spDoc2   ); //递归枚举当前子框架   IHTMLDocument2   上的表单form  
  }  
  }  
   
  void   EnumForm(   IHTMLDocument2   *   pIHTMLDocument2   )  
  {  
  if(   !pIHTMLDocument2   ) return;  
   
  EnumFrame(   pIHTMLDocument2   ); //递归枚举当前   IHTMLDocument2   上的子框架fram  
   
  HRESULT   hr;  
  CComBSTR   bstrTitle;  
  pIHTMLDocument2->get_title(   &bstrTitle   ); //取得文档标题  
   
  USES_CONVERSION;  
  cout   <<   _T("====================")   <<   endl;  
  cout   <<   _T("开始枚举“")   <<   OLE2CT(   bstrTitle   )   <<   _T("”的表单")   <<   endl;  
  cout   <<   _T("====================")   <<   endl;  
   
  CComQIPtr<   IHTMLElementCollection   >   spElementCollection;  
  hr   =   pIHTMLDocument2->get_forms(   &spElementCollection   ); //取得表单集合  
  if   (   FAILED(   hr   )   )  
  {  
  cout   <<   _T("获取表单的集合   IHTMLElementCollection   错误")   <<   endl;  
  return;  
  }  
   
  long   nFormCount=0; //取得表单数目  
  hr   =   spElementCollection->get_length(   &nFormCount   );  
  if   (   FAILED(   hr   )   )  
  {  
  cout   <<   _T("获取表单数目错误")   <<   endl;  
  return;  
  }  
   
  for(long   i=0;   i<nFormCount;   i++)  
  {  
  IDispatch   *pDisp   =   NULL; //取得第   i   项表单  
  hr   =   spElementCollection->item(   CComVariant(   i   ),   CComVariant(),   &pDisp   );  
  if   (   FAILED(   hr   )   ) continue;  
   
  CComQIPtr<   IHTMLFormElement   >   spFormElement   =   pDisp;  
  pDisp->Release();  
   
  long   nElemCount=0; //取得表单中   域   的数目  
  hr   =   spFormElement->get_length(   &nElemCount   );  
  if   (   FAILED(   hr   )   ) continue;  
   
  for(long   j=0;   j<nElemCount;   j++)  
  {  
  CComDispatchDriver   spInputElement; //取得第   j   项表单域  
  hr   =   spFormElement->item(   CComVariant(   j   ),   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;  
   
  LPCTSTR   lpName   =   vName.bstrVal?  
  OLE2CT(   vName.bstrVal   )   :   _T("NULL"); //未知域名  
  LPCTSTR   lpVal     =   vVal.bstrVal?  
  OLE2CT(   vVal.bstrVal     )   :   _T("NULL"); //空值,未输入  
  LPCTSTR   lpType   =   vType.bstrVal?  
  OLE2CT(   vType.bstrVal   )   :   _T("NULL"); //未知类型  
   
  cout   <<   _T("[")   <<   lpType   <<   _T("]   ");  
  cout   <<   lpName   <<   _T("   =   ")   <<   lpVal   <<   endl;  
  }  
  //想提交这个表单吗?删除下面语句的注释吧  
  //pForm->submit();  
  }  
  }Top

6 楼jiangsheng(蒋晟.Net[MVP])回复于 2006-05-31 11:30:59 得分 0

Frame元素支持IWebBrowser2接口Top

7 楼jinhe1314(hoyoo)回复于 2006-05-31 11:31:23 得分 0

to   lion_wing  
  用蒋老大的方法枚举复杂的网页太慢了,用我上面的方法快,但是得不出IHTMLFrameBase接口他永远是NULLTop

8 楼jinhe1314(hoyoo)回复于 2006-05-31 11:37:22 得分 0

to   蒋老大  
  是的“Frame元素支持IWebBrowser2接口”但是得不出,正确的“Frame”中的“输入框”位(需要吧Frame偏移加上才行)  
  Top

9 楼lion_wing(凤之焚-业与情的纠缠,死而复生的蜕变!)回复于 2006-05-31 11:41:02 得分 50

CComPtr<IHTMLDocument3>   pDoc3;  
  hr   =   pDoc2->QueryInterface(IID_IHTMLDocument3,(void**)&pDoc3)   ;  
  if(hr==S_OK)  
  {  
  CComBSTR   bstrName("FRAME");  
  CComPtr<IHTMLElementCollection>   pElemCollFrame;  
  hr=pDoc3->getElementsByTagName(bstrName,&pElemCollFrame);  
  if   (hr==S_OK)  
  {  
  long   pLength;  
  hr=pElemCollFrame->get_length(&pLength);  
  if(hr==S_OK)  
  {  
  for(int   i=0;i<pLength;i++)  
  {  
  IDispatch   *pDispFrame=NULL;  
  CComVariant   vIndex=i;  
  hr=pElemCollFrame->item(vIndex,vIndex,&pDispFrame);  
  if(hr==S_OK)  
  {  
  CComPtr<IHTMLElement>   pElemFrame;  
  hr=pDispFrame->QueryInterface(IID_IHTMLElement,(void**)&pElemFrame);    
  if(hr==S_OK)  
  {  
  CComPtr<IHTMLFrameBase2>   pFrameBase2;  
  hr=pElemFrame->QueryInterface(IID_IHTMLFrameBase2,(void**)&pFrameBase2);  
  if(hr==S_OK)  
  {  
  CComPtr<IHTMLWindow2>   pWindow2;  
  hr=pFrameBase2->get_contentWindow(&pWindow2);  
  if(hr==S_OK)  
  {  
  CComPtr<IHTMLDocument2>   pDoc2Frame;  
  hr=pWindow2->get_document(&pDoc2Frame);  
  if   (hr==S_OK)  
  {  
  //得到IHTMLDocument2  
  }  
  }  
  }  
  }  
  }  
  pDispFrame->Release();  
  }  
  }  
  }  
  }  
  不好意思,代码没整理!Top

10 楼jinhe1314(hoyoo)回复于 2006-05-31 13:21:28 得分 0

感谢俩位老大,问题解决,应该给你两位每人100分,但是我只有100分只好每人50分,  
  再一次的感谢两位。Top

11 楼LVOLCANO(风起)回复于 2006-07-12 15:45:05 得分 0

MarkTop

12 楼whisperLin()回复于 2006-09-19 17:43:06 得分 0

mark

阅读全文
0 0

相关文章推荐

img
取 消
img