我使用 MFC CHtmlView 类视图打开了目标网页,里面有个div如下,该div内容是通过ajax动态获取的,html源文件是没有内容的,打开网页后,内容已经显示出来了,请教如何获取到该div的内容?
参考GPT和自己的思路,你可以使用 IHTMLDocument2 接口来获取 CHtmlView 中的 HTML 文档对象,并通过 getElementById 方法获取指定的 div 元素。
以下是一个示例代码,可以获取名为 block_content 的 div 元素的内容:
// 获取 CHtmlView 中的 HTML 文档对象
IHTMLDocument2* pDoc = NULL;
if (SUCCEEDED(m_pBrowserApp->get_Document((IDispatch**)&pDoc)))
{
// 获取名为 "block_content" 的 div 元素
VARIANT varDivID;
VariantInit(&varDivID);
varDivID.vt = VT_BSTR;
varDivID.bstrVal = SysAllocString(L"block_content");
IDispatch* pDiv = NULL;
if (SUCCEEDED(pDoc->getElementById(varDivID, &pDiv)))
{
// 获取 div 元素的 HTML 内容
IHTMLElement* pElem = NULL;
if (SUCCEEDED(pDiv->QueryInterface(IID_IHTMLElement, (void**)&pElem)))
{
BSTR bstrHTML;
if (SUCCEEDED(pElem->get_innerHTML(&bstrHTML)))
{
CString strHTML(bstrHTML);
// 输出 div 元素的内容
TRACE(_T("div content: %s\n"), strHTML);
SysFreeString(bstrHTML);
}
pElem->Release();
}
pDiv->Release();
}
VariantClear(&varDivID);
pDoc->Release();
}
在上面的代码中,m_pBrowserApp 是 CHtmlView 类中的成员变量,用于获取 IWebBrowser2 接口的指针。getElementById 方法可以根据 div 元素的 ID 属性获取元素对象,get_innerHTML 方法可以获取元素的 HTML 内容。
该回答引用ChatGPT
您可以尝试使用IHTMLDocument2接口中的getElementById()方法来获取该div元素的内容。
首先,您需要获取到当前CHtmlView类视图中显示的HTML文档,可以通过以下代码实现:
IHTMLDocument2* pDoc = GetHtmlDocument();
然后,使用getElementById()方法获取div元素,并将其转换为IHTMLElement接口,代码如下:
CComVariant vId(L"block content");
CComPtr<IDispatch> spElemDispatch;
CComPtr<IHTMLElement> spElem;
HRESULT hr = pDoc->getElementById(vId, &spElemDispatch);
if (SUCCEEDED(hr) && spElemDispatch != NULL) {
hr = spElemDispatch->QueryInterface(IID_IHTMLElement, (void**)&spElem);
}
最后,您可以使用IHTMLElement接口中的get_innerHTML()方法获取该div元素的内容,代码如下:
if (spElem != NULL) {
CComBSTR bstrInnerHTML;
spElem->get_innerHTML(&bstrInnerHTML);
// 使用 bstrInnerHTML 获取 div 元素的内容
}
需要注意的是,该方法获取到的内容是div元素的innerHTML属性,如果div元素的内容是通过JavaScript动态生成的,则可能无法获取到完整的内容。
注册一个回调函数,该函数将在CHtmlView的文档加载完成后被调用,使用OnDocumentComplete()函数来注册这个回调函数。在回调函数中,获取div的IHTMLElement接口指针,然后调用其innerHTML属性,以获取div的内容。下面是一个示例代码,用于获取名为 "myDiv" 的 div 的内容:
void CMyHtmlView::OnDocumentComplete(LPCTSTR lpszURL)
{
CHtmlView::OnDocumentComplete(lpszURL);
// 获取文档中的元素
CComPtr<IHTMLDocument2> spDoc = GetHtmlDocument();
CComPtr<IDispatch> spDisp;
CComPtr<IHTMLElement> spElement;
spDoc->get_all(&spDisp);
spDisp->QueryInterface(IID_IHTMLElement, (void**)&spElement);
// 获取指定名称的元素
CString strElementName = _T("myDiv");
CComVariant varName = strElementName.AllocSysString();
CComPtr<IDispatch> spDisp2;
spElement->get_elementsByName(varName, &spDisp2);
CComPtr<IHTMLElementCollection> spCollection;
spDisp2->QueryInterface(IID_IHTMLElementCollection, (void**)&spCollection);
// 获取指定名称的元素中的第一个元素
long lCount = 0;
spCollection->get_length(&lCount);
if (lCount > 0)
{
CComVariant varIndex((long)0);
CComPtr<IDispatch> spDisp3;
spCollection->item(varIndex, varIndex, &spDisp3);
CComPtr<IHTMLElement> spElement2;
spDisp3->QueryInterface(IID_IHTMLElement, (void**)&spElement2);
// 获取元素的 innerHTML 属性
CComBSTR bstrHTML;
spElement2->get_innerHTML(&bstrHTML);
// 将 innerHTML 转换为 CString
CString strHTML(bstrHTML);
TRACE(_T("myDiv contents: %s\n"), strHTML);
}
}
1 获取CHtmlView的文档对象
要获取CHtmlView的文档对象,您可以使用CHtmlView::GetHtmlDocument()方法。此方法返回一个CDocument对象指针,该对象表示当前HTML文档。
CDocument* pDoc = GetHtmlDocument();
2 获取DIV元素对象
要获取指定的DIV元素对象,您可以使用CDocument::GetElementById()方法。此方法需要一个参数,即DIV元素的ID属性值。如果找到了具有指定ID的元素,该方法将返回一个CElement对象指针,否则返回NULL。
CElement* pDivElem = pDoc->GetElementById(_T("div_id"));
3 获取DIV元素的内容
如果找到了指定ID的DIV元素,您可以通过访问CElement对象的innerHTML属性获取其内容。innerHTML属性是一个CComBSTR对象,它表示DIV元素的HTML内容。
if (pDivElem != NULL)
{
CComBSTR bstrContent;
pDivElem->get_innerHTML(&bstrContent);
// 将CComBSTR转换为CString
CString strContent = CString(bstrContent);
}
完成这些步骤后,您将获得指定DIV元素的HTML内容。请注意,如果DIV元素包含子元素,innerHTML属性将返回包括所有子元素的完整HTML代码。如果您只需要DIV元素的文本内容,您可以使用CElement::GetInnerText()方法获取其文本内容。
以下答案基于ChatGPT与GISer Liu编写:
您可以使用 CHtmlView 类的 Navigate 方法来加载网页,并在网页加载完成后获取 div 内容。具体步骤如下:
在 CHtmlView 的 OnNavigateComplete2 方法中,使用 GetHtmlDocument 方法获取网页的 HTML 文档对象。
使用该 HTML 文档对象的 GetElementById 方法获取目标 div 对象。
使用该目标 div 对象的 innerHTML 属性获取 div 内容。
以下是一个完整的 MFC 代码示例,可以打开目标网页并获取指定 div 内容:
// MyHtmlView.h
class MyHtmlView : public CHtmlView
{
public:
virtual void OnNavigateComplete2(LPCTSTR strURL);
};
// MyHtmlView.cpp
#include "stdafx.h"
#include "MyHtmlView.h"
void MyHtmlView::OnNavigateComplete2(LPCTSTR strURL)
{
CHtmlView::OnNavigateComplete2(strURL);
// 获取 HTML 文档对象
CComPtr<IHTMLDocument2> spDoc = GetHtmlDocument();
if (!spDoc)
return;
// 获取目标 div 对象
CComPtr<IHTMLElement> spDiv;
spDoc->getElementById(L"target_div", &spDiv);
if (!spDiv)
return;
// 获取 div 内容
CComBSTR bstrHtml;
spDiv->get_innerHTML(&bstrHtml);
// 将内容转换为 CString 类型并输出
CString strHtml(bstrHtml);
AfxMessageBox(strHtml);
}
上述代码中的 “target_div” 是您要获取的目标 div 元素的 ID,您需要将其替换为实际的 ID。
仅供参考:
可以通过CHtmlView的成员函数ExecWB来执行JavaScript代码获取该div的内容。具体步骤如下:
1.在 CHtmlView 派生类的头文件中添加以下声明:
void OnDocumentComplete(LPCTSTR lpszURL);
2.在 CHtmlView 派生类的实现文件中添加以下代码:
void CHtmlViewDerived::OnDocumentComplete(LPCTSTR lpszURL)
{
CHtmlView::OnDocumentComplete(lpszURL);
if (lpszURL != NULL)
{
CString strScript;
strScript.Format(_T("var divContent = document.getElementsByClassName('block_content')[0].innerHTML; window.external.GetDivContent(divContent);"));
ExecWB(OLECMDID_OPTICAL_ZOOM, OLECMDEXECOPT_DONTPROMPTUSER, NULL, NULL);
ExecWB(OLECMDID_SCRIPT, OLECMDEXECOPT_DONTPROMPTUSER, &strScript, NULL);
}
}
void CHtmlViewDerived::GetDivContent(LPCTSTR lpszContent)
{
CString strContent(lpszContent);
// TODO: 处理获取到的内容
}
在 OnDocumentComplete 中,首先获取该div的内容的JavaScript代码存放在 strScript 变量中,然后调用 ExecWB 函数执行该代码。该函数的第一个参数是 OLECMDID_SCRIPT,表示执行JavaScript代码,第二个参数是 OLECMDEXECOPT_DONTPROMPTUSER,表示执行代码时不提示用户。第三个参数是 JavaScript 代码,第四个参数是输出参数,表示执行结果,我们不需要使用该参数。
在 JavaScript 代码中,我们首先通过 document.getElementsByClassName('block_content')[0] 获取到该 div 的节点对象,然后通过 innerHTML 获取到该 div 的内容。最后,我们调用外部程序的 GetDivContent 函数,将获取到的内容作为参数传递过去。
GetDivContent 是外部程序的一个函数,用于接收获取到的 div 内容。在该函数中,我们可以对获取到的内容进行处理。