【问题标题】:How to get access of <iframe> body using c++/ATL/COM?如何使用 c++/ATL/COM 访问 <iframe> 正文?
【发布时间】:2011-03-17 23:46:26
【问题描述】:

我编写了一个浏览器帮助对象来获取标签之间的文本并将其用于数据挖掘目的。我尝试在igoogle 上使用它(基本上是为了测试它在小工具上的功能),但在某些外部源存在&lt;iframe&gt; 的情况下它失败了。

我可以得到&lt;div&gt; 及其子&lt;iframe&gt;,但无法得到身体。

我从这个 API HRESULT IHTMLDocument2::get_frames(IHTMLFramesCollection2 **p);得到帧集合

可以使用loan calculator 小工具在 igoogle 和 firefox 中重新创建该问题。您还需要 fire bug 扩展来调试页面。出于参考目的,我在此处粘贴示例...

<div class="modboxin" id="m_8_b"><div style="border: 0pt none; padding: 0pt; margin: 0pt; width: 100%;" id="remote_8">
<iframe scrolling="no" frameborder="0" onload="_ifr_ol(this)" style="border: 0pt none; padding: 0pt; margin: 0pt; width: 100%; height: 100px; overflow: hidden;" name="remote_iframe_8" id="remote_iframe_8" src="http://8.ig.gmodules.com/gadgets/ifr?exp_rpc_js=1&amp;exp_track_js=1&amp;v=682f3db70d7cfff515d7c64fd24923&amp;container=ig&amp;view=default&amp;debug=0&amp;mid=8&amp;lang=en&amp;url=http%3A%2F%2Fwww.nova.edu%2F%7Ewillheat%2Floan.xml&amp;country=US&amp;parent=http://www.google.com&amp;libs=core:core.io:core.iglegacy:auth-refresh&amp;synd=ig&amp;view=default#st=...B27zWVKsnJu6OviCNnzXoPjkDsbPg95yZNMwfmMaLnwWoRxGaRArxTpOqK4TiH87uGUiHnYkkaqU9NE1sOyms6sg/Jwi&amp;gadgetId=116809661812082345195&amp;gadgetOwner=105250506097979753968&amp;gadgetViewer=105250506097979753968&amp;rpctoken=422312139&amp;ifpctok=422312139">
</iframe>
</div>

链接不完整,因为我已将src 的某些部分替换为...。现在您可以看到,虽然它在浏览器中呈现,但没有主体。

根据这篇文章 (http://stackoverflow.com/questions/957133/does-body-onload-wait-for-iframes),body 上的 onload 事件不会等待帧完成。

所以我可以得出结论,我必须为&lt;iframe&gt; 使用某种onload 侦听器...但我不确定如何...

请建议一种方法/sn-p 使用 ATL/COM API 检索 &lt;iframe&gt; 的正文...

** 更新**

我正在使用以下代码获取&lt;iframes&gt;。虽然我得到了 iframe 集合,但是当我尝试获取他们的身体时它失败了......可能是因为那时他们还没有加载?!

void testFrame(IHTMLDocument2* pDocument)
{
    CComQIPtr<IHTMLFramesCollection2> col;
    HRESULT hr = pDocument->get_frames(&col);
    if((hr == S_OK) && (col != NULL))
    {
        long counter = 0;
        hr = col->get_length(&counter);
        if((hr == S_OK) && (counter > 0))
        {
            for (int i = 0; i < counter; i++)
            {
                VARIANT     v1, v2;
                v1.vt = VT_I4; v1.lVal = i;
                VariantClear (&v2);
                hr = col->item(&v1, &v2);

                if (hr == S_OK && (v2.vt == VT_DISPATCH))
                {
                    CComPtr<IDispatch> pDispatch = v2.pdispVal;
                    CComQIPtr<IHTMLWindow2, &IID_IHTMLWindow2> pFrame = pDispatch;

                    if(pFrame)
                    {
                        CComPtr<IHTMLDocument2> spHTML;
                        hr = pFrame->get_document (&spHTML);

                        if((hr == S_OK) && (spHTML != NULL))
                        {
                            CComQIPtr<IHTMLElement> elem;
                            hr = spHTML->get_body(&elem);
                            if((hr == S_OK) && (elem != NULL))
                            {
                                CComBSTR str;
                                hr = elem->get_innerHTML(&str);
                                if((hr == S_OK) && (str != NULL))
                                {
                                    box(str);
                                }else if(hr != S_OK) {
                                    box(_T("hr is not ok"));
                                }else if(str == NULL){
                                    box(_T("STR is null"));
                                }else
                                    box(_T("Failed"));
                            }
                        }
                    }
                }
            }
        }
    }
}

还有,

void box(LPCWSTR msg)
{
    MessageBox(NULL,msg,_T("..BOX.."),MB_OK);
}

任何建议,如何获取 iframe 正文 .... 顺便说一下,我在 OnDocumentComplete 事件中处理这个...

谢谢,

【问题讨论】:

  • 对不起 - 你的问题到底是什么?
  • 嗨 Changeling,我正在尝试获取

标签: c++ com iframe atl bho


【解决方案1】:

而不是更新我自己的问题.. 我把这个作为答案。虽然我真的很想看到另一个答案......

--解决方案--

我的基本假设是:

  1. 我知道要处理的网址..
  2. 一个页面可以分为两个主要事件(也可能有其他事件,但这两个可以)
    • 主页面完成
    • 完成&lt;iframes&gt;

代码

void STDMETHODCALLTYPE CSafeMaskBHO::OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL)
{
    CComQIPtr<IWebBrowser2> spTempWebBrowser = pDisp;

    CComBSTR url = NULL;
    HRESULT hr = spTempWebBrowser->get_LocationURL(&url); // You can also take the url from pvarURL .. 

    if((hr == S_OK) && (url != NULL))
    {
        /*
            I know which url's I am looking for
        */
        if(!(wcsstr(url,_T("www.example.com")) != NULL) && !((wcsstr(url,_T("www.test.com")) != NULL))){
            return;
        }       

        CComPtr<IDispatch> frameDocDisp;
        hr = spTempWebBrowser->get_Document(&frameDocDisp);
        if((hr == S_OK) && (frameDocDisp != NULL))
        {
            CComQIPtr<IHTMLDocument3> spHTMLDoc = frameDocDisp;
            // ... Do someting useful ...

        }

    }else if(spTempWebBrowser && m_spWebBrowser && m_spWebBrowser.IsEqualObject(spTempWebBrowser))
    {
        CComPtr<IDispatch> spDispDoc;
        hr = m_spWebBrowser->get_Document(&spDispDoc);

        if ((hr == S_OK) && (spDispDoc != NULL))
        {
            CComQIPtr<IHTMLDocument2> spHTMLDoc = spDispDoc;
            if(spHTMLDoc)
            {
                // ... Do someting useful ...
            }
        }
    }
}

如果您认为您有什么要分享的(建议/更正/替代方案),那么请这样做.. :)

谢谢,

【讨论】:

    猜你喜欢
    • 2016-08-12
    • 2010-10-05
    • 2011-09-26
    • 2013-05-02
    • 2013-06-21
    • 1970-01-01
    • 1970-01-01
    • 2012-05-31
    • 2017-05-04
    相关资源
    最近更新 更多