Как получить доступ к телу <iframe>с помощью c ++ / ATL / COM? - PullRequest
0 голосов
/ 19 июля 2010

Я написал вспомогательный объект браузера, чтобы получить текст между тегами и использовать его в целях интеллектуального анализа данных.Я попытался использовать его на igoogle (в основном, чтобы проверить его работоспособность на гаджетах), и он потерпел неудачу в некоторых случаях, когда <iframe> присутствует с некоторым внешним источником.

Я могу получить <div> и его дочерний элемент <iframe>, но не могу получить тело.

Я получаю коллекцию фреймов из этого API HRESULT IHTMLDocument2::get_frames(IHTMLFramesCollection2 **p);

проблема может быть воссоздана в igoogle и firefox с помощью гаджета loan calculator.Вам также понадобится расширение пожарной ошибки для отладки страницы.Для справки я вставляю образец здесь ...

<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 на ....Теперь, как вы видите, в браузере нет тела для отображения, хотя оно обрабатывается ..

Согласно этому сообщению (/811926/body-onload-zhdet-iframes) событие onload для тела не ожидает завершения кадров.

Итак, я могу сделать вывод, что для <iframe> должен использоваться какой-то onload слушатель, но я не уверен, как ...

Пожалуйста, предложите способ / фрагментчтобы получить тело <iframe> с помощью API-интерфейсов ATL / COM ...

** Обновление **

Я использую следующий код для получения <iframes>.Хотя я получаю коллекцию 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 событие ...

Спасибо,

1 Ответ

0 голосов
/ 21 июля 2010

Вместо того, чтобы обновлять свой собственный вопрос .. Я ставлю это как ответ.Хотя мне бы очень хотелось увидеть альтернативный ответ ...

- Решение -

Мои основные предположения:

  1. Я знаю о URL для обработки ..
  2. Страница может быть разделена на два основных события (могут быть и другие события, но эти два тоже подойдут)
    • Завершение главной страницы
    • Завершение <iframes>

Код

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 ...
            }
        }
    }
}

Если вы считаете, что у вас есть что-топоделитесь (предложения / исправления / альтернативы) тогда сделайте так ..:)

Спасибо,

...