获取IE (控件)的所有链接(包括Frameset, iframe)

获取IE (控件)的所有链接(包括Frameset, iframe)

IE 顶层 body 节点通过IHTMLElement->get_all 方法无法获取iframe 里面的节点列表

CComPtr<IHTMLElement> body;
 
CComPtr<IDispatch> spDispCollection;
body->get_all(&spDispCollection);

所以要获取iframe/frame(frameset) 里面的节点列表的话, 则需要根据body/doc 找到frames, 然后从frames -> IHTMLWindow2 -> IHTMLDocument2 . 主要有2个方法, 下面是代码片段 
方法一: 
IHTMLDocument2 *pDoc = 浏览器的Document(IWebBrowser2->IDispatch->IHTMLDocument2); 
IHTMLWindow2 *pHTMLWnd = NULL; 
IHTMLDocument2 *pFrameDoc=NULL; 
IHTMLFramesCollection2 *pFramesCollection=NULL; 
LPDISPATCH lpDispatch; 

long p; 
VARIANT varindex,varresult; 
varresult.vt=VT_DISPATCH; 
varindex.vt = VT_I4; 
if(pDoc!=NULL) 

    HRESULT hr=pDoc->get_frames(&pFramesCollection); 
    if(SUCCEEDED(hr)&&pFramesCollection!=NULL) 
    { 
        hr=pFramesCollection->get_length(&p); 
        if(SUCCEEDED(hr)) 
            for(int i=0; i<p; i++) 
            { 
                varindex.lVal = i; 
                if(pFramesCollection->item(&varindex, &varresult) ==S_OK) 
                { 
                    lpDispatch=(LPDISPATCH)varresult.ppdispVal; 
                    if (SUCCEEDED(lpDispatch->QueryInterface(IID_IHTMLWindow2, (LPVOID *)&pHTMLWnd))) 
                    { 
                        if(SUCCEEDED(pHTMLWnd->get_document( &pFrameDoc))) 
                        { 
                            //work with the pFrameDoc  
                        } 
                        pHTMLWnd->Release(); 
                        pHTMLWnd=NULL; 
                    } 
                } 
            } 
            pFramesCollection->Release(); 
    } 
    pDoc->Release(); 
}

方法二:
CComQIPtr<IHTMLElement> pElem = ; // 可以递归上面的 CComPtr<IDispatch> spDispCollection 来得到 
CComBSTR bstrTagName;
pElem->get_tagName(&bstrTagName);
if ( lstrcmpiW(L"IFRAME", bstrTagName)==0 ||
        lstrcmpiW(L"FRAME", bstrTagName)==0 )
{
    CComQIPtr<IHTMLFrameBase2>    _framebase2;
    CComPtr<IHTMLWindow2>        _framewindow;
    CComPtr<IHTMLDocument2>        _framedoc;
    
    if( (_framebase2 = spItem) 
        && SUCCEEDED( _framebase2->get_contentWindow(&_framewindow) ) && _framewindow!=NULL 
        && SUCCEEDED( _framewindow->get_document(&_framedoc) ) && _framedoc!=NULL )
    {
        // 对 _framedoc 节点进行处理
    }
}


iframe 跨域访问(cross frame)  zz from : http://codecentrix.blogspot.com/2007/10/when-ihtmlwindow2getdocument-returns.html 
由于安全性限制, 为防止跨域脚本攻击, 当frames 跨域的时候, IHTMLWindow2::get_document 调用将返回 E_ACCESSDENIED . 
下面函数 HtmlWindowToHtmlDocument  对于跨域的frame 通过 IHTMLWindow2 -> IID_IWebBrowserApp -> IHTMLWindow2 绕过了限制.

// 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.
CComQIPtr<IHTMLDocument2> HtmlWindowToHtmlDocument(CComQIPtr<IHTMLWindow2> spWindow)
{
     ATLASSERT(spWindow != NULL);

     CComQIPtr<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.
     CComQIPtr<IWebBrowser2>  spBrws = HtmlWindowToHtmlWebBrowser(spWindow);
     if (spBrws == NULL)
     {
          return CComQIPtr<IHTMLDocument2>();
     }

     // Get the document object from the IWebBrowser2 object.
     CComQIPtr<IDispatch> spDisp;
     hRes = spBrws->get_Document(&spDisp);
     spDocument = spDisp;

     return spDocument;
}


// Converts a IHTMLWindow2 object to a IWebBrowser2. Returns NULL in case of failure.
CComQIPtr<IWebBrowser2> HtmlWindowToHtmlWebBrowser(CComQIPtr<IHTMLWindow2> spWindow)
{
     ATLASSERT(spWindow != NULL);

     CComQIPtr<IServiceProvider>  spServiceProvider = spWindow;
     if (spServiceProvider == NULL)
     {
          return CComQIPtr<IWebBrowser2>();
     }

     CComQIPtr<IWebBrowser2> spWebBrws;
     HRESULT hRes = spServiceProvider->QueryService(IID_IWebBrowserApp, IID_IWebBrowser2, (void**)&spWebBrws);
     if (hRes != S_OK)
     {
          return CComQIPtr<IWebBrowser2>();
     }

     return spWebBrws;
}


附: 
IE(控件/接口)中主要有4个部分, Browser, Document, Frame/IFrame, Element , 其对应接口分别是 
Browser         -    IWebBrowser2
Document      -    IHTMLDocument2
Frame/IFrame-    IHTMLWindow2
Element         -    IHTMLElement
可以通过下面方法互相获取 
browser      -> document        IWebBrowser2::get_Document
document     -> frame           IHTMLDocument2::get_parentWindow
frame        -> document        IHTMLWindow2::get_document
frame        -> parent frame    IHTMLWindow2::get_parent
frame        -> children frames IHTMLWindow2::get_frames
element     -> Frame             IHTMLElement->QI(IHTMLFrameBase2) -> IHTMLFrameBase2->get_contentWindow -> IHTMLWindow2 

ref: 
在多Frame的网页中怎么取出各个Frame的IHTMLDocument2的接口!急用.(高分)
在文章  When IHTMLWindow2::get_document returns E_ACCESSDENIED 解决了iframe 跨域访问的问题 

posted on 2008-07-30 19:17 泡泡牛 阅读(5153) 评论(3)  编辑 收藏 引用 所属分类: Develop

 

转载于:https://www.cnblogs.com/honeynm/p/4438305.html

Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计,皆可应用在项目、毕业设计、课程设计、期末/期/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值