웹브라우저 컨트롤을 사용할 때, 프로그램에서 로드된 도큐먼트의 소스를 가져오고 싶을 때가 있다. 인터넷 익스플로러에서 `보기` / `소스` 를 했을 때처럼 말이다. 쉬울듯하나 그리 간단하지는 않다.

 

제일 쉬운방법은 IHTMLDocument3에 있는 documentElement 개체를 얻어다 이것의 OuterHTML 프로퍼티를 읽어오는 것이다. 제법 그럴듯한 게 나오므로 대부분의 경우 이 방법을 사용하면 문제가 없다. 단 하나의 문제는 여기에 나오는 것이 웹서버가 준 도큐먼트 소스가 아니라 인터넷 익스플로러의 HTML 파서가 한 번 파싱해 놓은 도큐먼트라는 것이다. 그래서 서버가 준 것과 똑 같은 도큐먼트를 얻고자 할 때는 사용할 수가 없다.

 

그래서 일반적으로 할 수 있는 방법은 IHTMLDocument2로부터 IPersistStreamInit을 얻어와서 이것의 Save() 메쏘드를 이용하는 것이다. 이걸 할려면 IStream 개체가 있어야 하는데 ::CreateStreamOnHGlobal()이라는 아주 훌륭한 넘으로 쉽게 맹글 수 있다. 처음엔 HGlobal을 만들고 위에 함수를 불렀는데, 읽어올 도큐먼트의 크기를 미리 알아야 한다는 문제가 있었다. 하지만 그냥 NULL을 ::CreateStreamOnHGlobal()에 넘겨주면 알아서 메모리를 할당하므로 크기를 알아올 필요가 없어져서 좋다. 내부 버퍼를 알아올라면 ::GetHGlobalFromStream()을 쓰면 된다.

 

MSDN 어딘가를 뒤져보며 있는데 위치를 까먹었다. ㅠㅠ

 

// 웹브라우저 컨트롤에서 가져화서 설정한다.

// 설정하는 방법은 다른데서 설명하기로 하자.

IHTMLDocument pDoc;

 

IStream * pStream = NULL;
IPersistStreamInit * pPSI = NULL;

HGLOBAL hHTMLContent;
HRESULT hr;
bool bResult = false;
BYTE* buff = NULL; // 여기다 소스를 담는다

 

hr = ::CreateStreamOnHGlobal(NULL, TRUE, &pStream);
if (SUCCEEDED(hr))
{
    // request the IPersistStreamInit interface
    hr = pDoc->QueryInterface(IID_IPersistStreamInit, (void **) &pPSI);
    if (SUCCEEDED(hr))
    {
        hr = pPSI->Save(pStream, FALSE);
        if (SUCCEEDED(hr))
        {
            hr = ::GetHGlobalFromStream(pStream, &hHTMLContent);
            if (SUCCEEDED(hr))
            {
                bResult = true;
                LPVOID data = ::GlobalLock(hHTMLContent);
                DWORD size = ::GlobalSize(hHTMLContent);
                buff = new BYTE[size + 1];
                ::memcpy(buff, data, size);
                buff[size] = '\0';
                ::GlobalUnlock(hHTMLContent);
            }
        }
        pPSI->Release();
    }
    // implicitly calls ::GlobalFree to free the global memory
    pStream->Release();
}

 =======================================================================================================
[다른방법]

홈페이지 소스 가져오기

//웹페이지 소스 가져오기
 IWebBrowser2* pBrowser2;

 HRESULT hr;

 hr=OleInitialize(NULL);

    if(!SUCCEEDED(hr))
        return FALSE;

 CoCreateInstance(CLSID_InternetExplorer, NULL, CLSCTX_LOCAL_SERVER, IID_IWebBrowser2, (LPVOID *)&pBrowser2);

  
      BSTR bstrURL = SysAllocString(L"http://news.naver.com/sports/new/main/index.nhn");

    if(pBrowser2)
    {  
 
    VARIANT vEmpty;
       VariantInit(&vEmpty);

       hr = pBrowser2->Navigate(bstrURL, &vEmpty, &vEmpty, &vEmpty, &vEmpty);
    }


 IHTMLDocument2*  pHTMLDocument2;
 LPDISPATCH lpDispatch;
 pBrowser2->get_Document(&lpDispatch);


 

 CString szSource = "";

    if (lpDispatch)
 {
  HRESULT hr;
  hr = lpDispatch->QueryInterface(IID_IHTMLDocument2, (LPVOID*)&pHTMLDocument2);
  lpDispatch->Release();

  IHTMLElement*  pBody;
  hr = pHTMLDocument2->get_body(&pBody);

  BSTR bstr;              
  pBody->get_innerHTML(&bstr);

  int nLen;
  char* szTarget;
  nLen = (int)wcslen(bstr) * 2 + 1;
  szTarget = new char[nLen];
     ::WideCharToMultiByte(CP_ACP, 0, bstr, -1, szTarget, nLen, NULL, NULL );

  szSource.Format("%s", szTarget);

   
  SysFreeString(bstr);
  pBody->Release();

  delete szTarget;


 }

 pBrowser2->Quit();

 SysFreeString(bstrURL);
    pBrowser2->Release();

 OleUninitialize();


 

Posted by 모과이IT
,