当前位置:编程学习 > C/C++ >>

如何定制一款12306抢票浏览器——实现自动查询和预定功能

     检查是否进入订票页面
 
        判断是否进入订票页面,我是确定了两个标准: 
 
        1 网址是否为http://www.12306.cn/mormhweb/kyfw/
 
        2 该页面否有查询按钮
 
[cpp]  
BOOL CDeal12306WebPage::IsQueryPage( CComPtr<IHTMLDocument2> & spDoc, CComBSTR & bstrUrl )  
{  
    HRESULT hr = E_FAIL;  
    do  {  
        CString cstrUrl = CString((LPWSTR)bstrUrl);  
        if ( 0 == cstrUrl.CompareNoCase(LOGIN12306URL) ) {  
            CComPtr<IHTMLElement> spQueryButton;  
            hr = GetQueryButtonInQueryPage( spDoc, spQueryButton);  
            CHECKHRPOINTER(hr, spQueryButton);  
        }  
    } while (0);  
    return FAILED(hr) ? FALSE : TRUE;  
}  
         URL很好检测,那么我们如何判断是否存在查询按钮呢?我们先看一下订票页面的页面特征。
        解决跨域问题
 
        可以见得订票页面内部嵌入了两个Iframe,而我们关心的那块页面恰恰就是最里面一层IFrame。那我们直接通过最外层的Doc获取到最里面的Doc,然后在最里面的Doc执行有关的查询操作即可。然而熟悉javascript的同学可能马上就会想到“跨域”问题。其实在浏览器层面,跨域问题是很好解决的。
 
[cpp]  
HRESULT CDeal12306WebPage::GetIFrameDoc( CComPtr<IHTMLDocument2>& spDoc,   
    const CString& cstrIFrameName, CComPtr<IHTMLDocument2>& spInnerDoc )  
{  
    HRESULT hr = E_FAIL;  
    do {  
        CComQIPtr<IHTMLFramesCollection2> spFrameCollection;  
        hr = spDoc->get_frames(&spFrameCollection);  
        CHECKHRPOINTER(hr, spFrameCollection);  
  
        CComVariant IframeNameReq = CComBSTR(cstrIFrameName.GetString());  
        CComVariant FramePage;  
        hr = spFrameCollection->item(&IframeNameReq, &FramePage);  
        CHECKHRPOINTER(hr,FramePage.pdispVal);  
  
        CComPtr<IHTMLWindow2> spIFramePage;  
        hr = FramePage.pdispVal->QueryInterface(IID_IHTMLWindow2, (LPVOID*)&spIFramePage);  
        CHECKHRPOINTER(hr, spIFramePage);  
  
        hr = spIFramePage->get_document(&spInnerDoc);  
        if ( E_ACCESSDENIED == hr ) {  
            CComQIPtr<IServiceProvider> spServiceProvider = spIFramePage;  
            CHECKPOINT(spServiceProvider);  
  
            CComQIPtr<IWebBrowser2> spInnerWebBrowser;  
            hr = spServiceProvider->QueryService(IID_IWebBrowserApp, IID_IWebBrowser2, (LPVOID*)&spInnerWebBrowser);  
            CHECKHRPOINTER(hr, spInnerWebBrowser);  
  
            CComPtr<IDispatch> spDisp;  
            hr = spInnerWebBrowser->get_Document(&spDisp);  
            CHECKHRPOINTER(hr, spDisp);  
  
            hr = spDisp->QueryInterface(IID_IHTMLDocument2, (LPVOID*)&spInnerDoc);  
            CHECKHRPOINTER(hr, spInnerDoc);  
        }  
    } while (0);  
    return hr;  
}  
        上面这个函数试图在spDoc页面中获取其内嵌的名字是cstrIFrameName的IFrame的Doc。于是我们要获取其中最里面一层Iframe的Doc可以如下调用
[cpp]  
HRESULT CDeal12306WebPage::GetIFrameNamedIFramePageDoc( CComPtr<IHTMLDocument2> & spDoc,   
    CComPtr<IHTMLDocument2> & spInnerDoc )  
{  
    HRESULT hr = E_FAIL;  
    do {  
        hr =  GetIFrameDoc(spDoc, L"iframepage", spInnerDoc);  
        CHECKHRPOINTER(hr, spInnerDoc);  
    } while (0);  
    return hr;  
}  
  
HRESULT CDeal12306WebPage::GetIFrameNamedMainDoc( CComPtr<IHTMLDocument2> & spIFramPageDoc,  
    CComPtr<IHTMLDocument2> & spMainDoc )  
{  
    HRESULT hr = E_FAIL;  
    do {  
        hr =  GetIFrameDoc(spIFramPageDoc, L"main", spMainDoc);  
        CHECKHRPOINTER(hr, spMainDoc);  
    } while (0);  
    return hr;  
}  
  
HRESULT CDeal12306WebPage::GetMainDoc( CComPtr<IHTMLDocument2> & spDoc,  
    CComPtr<IHTMLDocument2> & spMainDoc )  
{  
    HRESULT hr = E_FAIL;  
    do {  
        CComPtr<IHTMLDocument2> spIFramePageDoc;  
        hr = GetIFrameNamedIFramePageDoc(spDoc, spIFramePageDoc);  
        CHECKHRPOINTER(hr, spIFramePageDoc);  
  
        hr = GetIFrameNamedMainDoc(spIFramePageDoc, spMainDoc);  
        CHECKHRPOINTER(hr, spMainDoc);  
    } while (0);  
    return hr;  
}  
        当我们获得最里层的Doc后,我们将根据页面结构获取Class为cx_from的Table元素。
          获取这个Table的原因是,之后我们会以该Table为节点,执行“查询按钮”查找的操作。
 
[cpp]  
HRESULT CDeal12306WebPage::GetQueryButtonInQueryPage( CComPtr<IHTMLDocument2> & spDoc, CComPtr<IHTMLElement> & spQueryButtonElem )  
{  
    HRESULT hr = E_FAIL;  
    do  {  
        CComPtr<IHTMLDocument2> spMainDoc;  
        hr = GetMainDoc( spDoc, spMainDoc);  
      &nb
补充:软件开发 , C++ ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,