跪求通过指定网址获取IHTMEDocument指针实现提取内链现在我写了一个通过IE浏览器打开网站,然后获得IHTMLDocument2的指针,但我想随便给定一个网址,不打开IE浏览器的情况下获得IHTMLDocument2指针,感谢各位大神指点!以下是通过打开IE浏览器获得IHTMLDocument2指针代码,请大神们告诉我指定网址、不开IE浏览器情况下获取IHTMLDocument指针?????Initialize(NULL);//初始化COM
CComPtr<IShellWindows> spShellWin;
HRESULT hr=spShellWin.CoCreateInstance(CLSID_ShellWindows);
/*HRESULT hr = CoCreateInstance( CLSID_HTMLDocument, NULL, CLSCTX_INPROC_SERVER, IID_IHTMLDocument2, 
(void **)&spShellWin);
long nCount=0;
spShellWin->get_Count(&nCount);//取得浏览器实例个数
if (0==nCount)  return;     
for(long i=0;i<nCount;i++)
{
CComPtr<IDispatch> spDispIE;
hr=spShellWin->Item(CComVariant((long)i),&spDispIE);
if(FAILED(hr)) continue;
CComQIPtr<IWebBrowser2>spBrowser=spDispIE;
if(!spBrowser) continue;
CComPtr<IDispatch> spDispDoc; 
hr=spBrowser->get_Document(&spDispDoc);
if(FAILED(hr)) continue;
CComQIPtr<IHTMLDocument2> spDocument2=spDispDoc;
if(!spDocument2) continue;
// 程序运行到此,已经找到了IHTMLDocument2的接口指针       if(!spDocument2) return;
CComQIPtr<IHTMLElementCollection> spAllElement; 
        hr=spDocument2->get_links(&spAllElement);
                        //获取所有网页内所有内嵌网页链接
if (FAILED(hr))  return; 
long nLength = 0;
spAllElement->get_length (&nLength);
CString allstr;
for (int i = 0; i < nLength; i++)
{
CComPtr<IDispatch> pDisp;
hr = spAllElement->item(COleVariant((long)i),COleVariant((long)0),&pDisp); //获取单个链接

if(SUCCEEDED(hr)) 
{
CComQIPtr <IHTMLAnchorElement, &IID_IHTMLAnchorElement> pElement(pDisp);
BSTR bHref;
pElement->get_href(&bHref);
CString strHref=bHref;
allstr=allstr+strHref;
allstr=allstr+";";

}
}
CFile writemydata;
writemydata.Open("d:\\Href.txt",CFile::modeWrite|CFile::modeRead|CFile::modeCreate);
writemydata.Write(allstr,strlen(allstr)+1);
}

解决方案 »

  1.   

    没有浏览器对象,哪来的IHTMLDocument2接口呢?你这个问题貌似无解
      

  2.   

    IHTMLDocument2不一定需要从浏览器对象获取,可以先把网页下载到本地,然后本地加载文件。前提是这个网页需要是静态网页。
      

  3.   

    IHTMLDocument2不一定需要从浏览器对象获取,可以先把网页下载到本地,然后本地加载文件。前提是这个网页需要是静态网页。我希望代码对动态也有用的,我在网上看到这段代码 CComPtr<IConnectionPointContainer> pCPC = NULL;
    CComPtr<IConnectionPoint> pCP = NULL;
    CComPtr<IOleObject> pOleObject = NULL;
    CComPtr<IOleControl> pOleControl = NULL; // If no arguments were passed, load a default URL
    ::CoInitialize(NULL);

    m_nScheme = INTERNET_SCHEME_HTTP;
    // Create an instance of an dynamic HTML document
    HRESULT hr = CoCreateInstance( CLSID_HTMLDocument, 
    NULL, 
    CLSCTX_INPROC_SERVER, 
    IID_IHTMLDocument2, 
    (void **)&m_pMSHTML); if (FAILED(hr))
    return hr; if (FAILED(hr = m_pMSHTML->QueryInterface(IID_IOleObject, (void **)&pOleObject)))
    return hr; hr = pOleObject->SetClientSite(this); if (FAILED(hr = m_pMSHTML->QueryInterface(IID_IOleControl, (void **)&pOleControl)))
    return hr; hr = pOleControl->OnAmbientPropertyChange(DISPID_AMBIENT_USERMODE);
    assert(SUCCEEDED(hr));
    hr = pOleControl->OnAmbientPropertyChange(DISPID_AMBIENT_DLCONTROL);
    assert(SUCCEEDED(hr)); // Hook up sink to catch ready state property change
    if (FAILED(hr = m_pMSHTML->QueryInterface(IID_IConnectionPointContainer, (void **)&pCPC)))
    return hr; if (FAILED(hr = pCPC->FindConnectionPoint(IID_IPropertyNotifySink, &pCP)))
    return hr; if (FAILED(hr = pCP->Advise((IUnknown *)(IPropertyNotifySink *)this, &m_dwCookie)))
    return hr;
    然后......
    if (m_pMSHTML == NULL) return S_FALSE;
    CComPtr<IHTMLElementCollection> pElementCol = NULL;
    long p=0; if (!SUCCEEDED(m_pMSHTML->get_links(&pElementCol)))
    return S_FALSE;
    就得到所要的结果了这里的
    hr = pOleObject->SetClientSite(this);
    if (FAILED(hr = pCP->Advise((IUnknown *)(IPropertyNotifySink *)this, &m_dwCookie)))
    这两个this指针 搞不懂,我是基于对话框编程的,还请各位大侠指点
      

  4.   

    IHTMLDocument2不一定需要从浏览器对象获取,可以先把网页下载到本地,然后本地加载文件。前提是这个网页需要是静态网页。
    IHTMLDocument2是Document文档对象提供的一个接口,所以浏览器对象是必须的,当然这个浏览器对象是广义的,并不一定非得是IE那个WebBrowser,也可以是其他方或者是自己实现的。但实现一个网页解析器是何等的困难,所以还不如直接用已有的浏览器内核了。
    至于网页文件本地加载也好,从网上加载也罢,倒确实没有分别。
    下面那段代码貌似是从实现IE插件的一段代码,实例化GetSite的接口
      

  5.   

    还有一个常识,网页无论是动态还是静态,浏览器请求时,Web服务器返回的都是静态文件,动态或静态是服务器端的术语,意味着网页是即时生成的,还是预先就准备好的。当然,保存到本地后,那也肯定就是静态的了。
      

  6.   


    多谢你的指点,我看到那段代码,别人也是基于对话框的,不用打开浏览器就可以实现获取links
    CComPtr<IHTMLDocument2> m_pMSHTML
    CComPtr<IHTMLElementCollection> pElementCol = NULL;
    if (!SUCCEEDED(m_pMSHTML->get_links(&pElementCol)))
    所以现在困惑就在,不用打开浏览器,输入一个网址就可以获取到IHTMLDocument2指针 最终获取到links
      

  7.   


    多谢你的指点,我看到那段代码,别人也是基于对话框的,不用打开浏览器就可以实现获取links
    CComPtr<IHTMLDocument2> m_pMSHTML
    CComPtr<IHTMLElementCollection> pElementCol = NULL;
    if (!SUCCEEDED(m_pMSHTML->get_links(&pElementCol)))
    所以现在困惑就在,不用打开浏览器,输入一个网址就可以获取到IHTMLDocument2指针 最终获取到links如果可以,你能不能把那个程序发给我看看?
    按照我的理解,不打开浏览器当然是可以的,可以在对话框里面嵌入一个WebBrowser控件(或者动态创建),根据需要可以把这个控件隐藏掉,用这个WebBrowser加载文件即可,再获取这个空间的Docment对象,就可以获取全部链接了。至于没有浏览器对象就直接用IHTMLDocument2,无法想想,IHTMLDocument2只是一个接口而已,其功能实现全部在浏览器对象内部。delphi和vb这里稍高级的语言,对这些东西都有很好的封装,使用很简单。但VC做这些,就复杂多了。
      

  8.   


    多谢你的指点,我看到那段代码,别人也是基于对话框的,不用打开浏览器就可以实现获取links
    CComPtr<IHTMLDocument2> m_pMSHTML
    CComPtr<IHTMLElementCollection> pElementCol = NULL;
    if (!SUCCEEDED(m_pMSHTML->get_links(&pElementCol)))
    所以现在困惑就在,不用打开浏览器,输入一个网址就可以获取到IHTMLDocument2指针 最终获取到links如果可以,你能不能把那个程序发给我看看?
    按照我的理解,不打开浏览器当然是可以的,可以在对话框里面嵌入一个WebBrowser控件(或者动态创建),根据需要可以把这个控件隐藏掉,用这个WebBrowser加载文件即可,再获取这个空间的Docment对象,就可以获取全部链接了。至于没有浏览器对象就直接用IHTMLDocument2,无法想想,IHTMLDocument2只是一个接口而已,其功能实现全部在浏览器对象内部。delphi和vb这里稍高级的语言,对这些东西都有很好的封装,使用很简单。但VC做这些,就复杂多了。 请告诉一下你的邮箱,我发给你 多谢
      

  9.   


    多谢你的指点,我看到那段代码,别人也是基于对话框的,不用打开浏览器就可以实现获取links
    CComPtr<IHTMLDocument2> m_pMSHTML
    CComPtr<IHTMLElementCollection> pElementCol = NULL;
    if (!SUCCEEDED(m_pMSHTML->get_links(&pElementCol)))
    所以现在困惑就在,不用打开浏览器,输入一个网址就可以获取到IHTMLDocument2指针 最终获取到links如果可以,你能不能把那个程序发给我看看?
    按照我的理解,不打开浏览器当然是可以的,可以在对话框里面嵌入一个WebBrowser控件(或者动态创建),根据需要可以把这个控件隐藏掉,用这个WebBrowser加载文件即可,再获取这个空间的Docment对象,就可以获取全部链接了。至于没有浏览器对象就直接用IHTMLDocument2,无法想想,IHTMLDocument2只是一个接口而已,其功能实现全部在浏览器对象内部。delphi和vb这里稍高级的语言,对这些东西都有很好的封装,使用很简单。但VC做这些,就复杂多了。 请告诉一下你的邮箱,我发给你 多谢[email protected]
      

  10.   


    多谢你的指点,我看到那段代码,别人也是基于对话框的,不用打开浏览器就可以实现获取links
    CComPtr<IHTMLDocument2> m_pMSHTML
    CComPtr<IHTMLElementCollection> pElementCol = NULL;
    if (!SUCCEEDED(m_pMSHTML->get_links(&pElementCol)))
    所以现在困惑就在,不用打开浏览器,输入一个网址就可以获取到IHTMLDocument2指针 最终获取到links如果可以,你能不能把那个程序发给我看看?
    按照我的理解,不打开浏览器当然是可以的,可以在对话框里面嵌入一个WebBrowser控件(或者动态创建),根据需要可以把这个控件隐藏掉,用这个WebBrowser加载文件即可,再获取这个空间的Docment对象,就可以获取全部链接了。至于没有浏览器对象就直接用IHTMLDocument2,无法想想,IHTMLDocument2只是一个接口而已,其功能实现全部在浏览器对象内部。delphi和vb这里稍高级的语言,对这些东西都有很好的封装,使用很简单。但VC做这些,就复杂多了。 请告诉一下你的邮箱,我发给你 多谢[email protected]已发,请查阅!
      

  11.   


    多谢你的指点,我看到那段代码,别人也是基于对话框的,不用打开浏览器就可以实现获取links
    CComPtr<IHTMLDocument2> m_pMSHTML
    CComPtr<IHTMLElementCollection> pElementCol = NULL;
    if (!SUCCEEDED(m_pMSHTML->get_links(&pElementCol)))
    所以现在困惑就在,不用打开浏览器,输入一个网址就可以获取到IHTMLDocument2指针 最终获取到links如果可以,你能不能把那个程序发给我看看?
    按照我的理解,不打开浏览器当然是可以的,可以在对话框里面嵌入一个WebBrowser控件(或者动态创建),根据需要可以把这个控件隐藏掉,用这个WebBrowser加载文件即可,再获取这个空间的Docment对象,就可以获取全部链接了。至于没有浏览器对象就直接用IHTMLDocument2,无法想想,IHTMLDocument2只是一个接口而已,其功能实现全部在浏览器对象内部。delphi和vb这里稍高级的语言,对这些东西都有很好的封装,使用很简单。但VC做这些,就复杂多了。 请告诉一下你的邮箱,我发给你 多谢[email protected]已发,请查阅!收到,晚上我仔细看看,再回复你
      

  12.   

    正好有时间,现在回复吧。代码里面有个CPageDownloader,实例化一个IE文档对象,然后通过该对象加载网址,但也可以加载本地文件的,也就是说你调用Run方法时,传入一个存在本地网页的文件名称也是可以的。其实他用的方法跟你的方法是很类似,他直接创建了文档对象,但并没有创建IE窗口。但他做得很巧妙,自己实现了几个浏览器对象必须的接口后,用来作为创建IHTMLDocument2对象的载体。你是直接通过IShellWindows获取当前IE窗口,然后再获取IHTMLDocument。所以我有点疑惑,你的具体需求是什么。如果你只是想“不开IE浏览器情况下获取IHTMLDocument指针”,你可以直接用他的代码或者在其上修改。CPageDownloader加载文件成功后,m_pMSHTML就是你要求的IHTMLDocument2,可以通过IHTMLDocument2->QueryInterface获取IHTMLDocument。多说一句,如果只是抓网址这种活,实在没必要整IE接口这里复杂又大损脑细胞的活。把文件读到内存后,用查找函数查找"a href=",简单又高效。正则表达式都可以免。我早些年做过IE工具栏项目,花过许多时间来学习IE相关的各种接口(其中各种复杂、接口之间的关联、除MSDN外无资料),很折寿,现在想这事头还疼。
      

  13.   

    WebBrowser组件内部使用另一个组件HTMLDocument(你的代码中CLSID_HTMLDocument创建的就是这种组件,暂时叫做文档组件),文档组件专门负责HTML的解析和DOM导航,而脚本解析执行、嵌套框架管理、OCX创建管理、事件处理、HTML渲染等都是由浏览器组件完成的,只有浏览器组件才需要一个容器窗口。文档组件只是一个非常普通的COM组件,甚至连OCX都不是,不需要创建浏览器容器窗口,那些SetClientSite之类的调用对它来说没有作用。如果只是简单的DOM导航、查找某个元素的属性或值,用文档组件就足够了,但是如果网页中的部分内容是通过脚本创建的,或者通过AJAX异步动态加载的,这个组件就完全无能为力了,因为它根本不会执行脚本代码,也不会加载任何OCX控件。记住一点:文档组件只负责DOM的解析和导航,超出它能力的需求就必须借助于浏览器组件。
      

  14.   

     多谢回复,我就想用他的那种方式获取到IHTMLDocument2的指针,但我不明白地方就是:如何通过一个网址在不加载浏览器的情况下,获取到IHTMLDocument2指针?
      

  15.   

    不客气,一起学习而已。
    如果把代码中的CPageDownloader类创建了IHTMLDocument2但没有出现IE窗口也算的话,这段代码就真的满足了你的要求了。
      

  16.   

    他的那段代码,确实可以实现我想要的功能,但我没有弄懂,里面如何从一个网址得到IHTMLDocument2指针,这个过程没有看明白,你如何看懂了 请告诉我一下
      

  17.   

    你重点看看CPageDownloader这个类,PageDownloader.cpp/h文件。
    里面有个Init方法,就是预先创建了一个IHTMLDocument2对象,不过没加载文件,所以其内容是空白的。
    后面有个LoadURL方法,里面细分加载方式,如果是本地文件,就直接读取了(LoadURLFromFile)。如果是网址,就用下载接口来下载获取(LoadURLFromMoniker)。
    LoadURL后,IHTMLDocument2的内容就有了,你可以进行各种操作。
      

  18.   

    这个流程看懂了,
    hr = pOleObject->SetClientSite(this);
    if (FAILED(hr = pCP->Advise((IUnknown *)(IPropertyNotifySink *)this, &m_dwCookie)))
    这两个地方的this 指针没弄明白
      

  19.   

    这个流程看懂了,
    hr = pOleObject->SetClientSite(this);
    if (FAILED(hr = pCP->Advise((IUnknown *)(IPropertyNotifySink *)this, &m_dwCookie)))
    这两个地方的this 指针没弄明白说实话,你难倒我了,我看IE资料已经过去多年了,细节的印象很模糊了,而且这些东西确实很复杂和麻烦。
    不知是否可以这么理解,IHTMLDocument2是需要与IE浏览器对象关联使用的,否则其中一些接口会缺少,导致不能很好的使用,甚至出错。所以不妨把这2句理解为告诉IHTMLDocument2,CPageDownloader就是它的IE对象。
      

  20.   

    这个流程看懂了,
    hr = pOleObject->SetClientSite(this);
    if (FAILED(hr = pCP->Advise((IUnknown *)(IPropertyNotifySink *)this, &m_dwCookie)))
    这两个地方的this 指针没弄明白说实话,你难倒我了,我看IE资料已经过去多年了,细节的印象很模糊了,而且这些东西确实很复杂和麻烦。
    不知是否可以这么理解,IHTMLDocument2是需要与IE浏览器对象关联使用的,否则其中一些接口会缺少,导致不能很好的使用,甚至出错。所以不妨把这2句理解为告诉IHTMLDocument2,CPageDownloader就是它的IE对象。
    仍然很感谢你,这段程序流程看顺畅了,但就是看不懂其中的代码 
      

  21.   

    这个流程看懂了,
    hr = pOleObject->SetClientSite(this);
    if (FAILED(hr = pCP->Advise((IUnknown *)(IPropertyNotifySink *)this, &m_dwCookie)))
    这两个地方的this 指针没弄明白说实话,你难倒我了,我看IE资料已经过去多年了,细节的印象很模糊了,而且这些东西确实很复杂和麻烦。
    不知是否可以这么理解,IHTMLDocument2是需要与IE浏览器对象关联使用的,否则其中一些接口会缺少,导致不能很好的使用,甚至出错。所以不妨把这2句理解为告诉IHTMLDocument2,CPageDownloader就是它的IE对象。
    仍然很感谢你,这段程序流程看顺畅了,但就是看不懂其中的代码 不必客气。建议你慢慢看msdn对这几个接口的说明,看明白了,程序就会理解了。
    只是微软把IE和Explorer封装到一起后,许多接口之间都有关联,但没有一份完整的文档介绍其中的关联性和哪些接口是必须的,就好比给你一个数据库文件后,里面很多表,但毫无说明,却要你理清各个表之间的字段的关联性,让人很苦恼,只能慢慢多次尝试。