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

如何定制一款12306抢票浏览器——处理预定页面和验证码自动识别功能

     判断是否进入预定页面
 
        我们先看一下预定页面的结构 
 
        可以见得,这个页面也是嵌入了两个IFrame。关于IFrame的跨域问题,我已经在前一篇文章中讲述了解决办法。
 
        我判断是否是预定页面是通过两个依据:
 
        1 URL是否是 
 
        2 是否可以在最里层IFrame中找到class是“table_qr”的元素该元素对应于
        具体的查找过程我这儿就不再赘述,我们通过代码来解读
 
[cpp] 
BOOL CDeal12306WebPage::IsBookingPage( CComPtr<IHTMLDocument2> & spDoc, CComBSTR & bstrUrl )  
{  
    HRESULT hr = E_FAIL;  
    do  {  
        CString cstrUrl = CString((LPWSTR)bstrUrl);  
        if ( 0 == cstrUrl.CompareNoCase(LOGIN12306URL) ) {  
            CComPtr<IHTMLElement> spTableQrTbody;  
            hr = GetTableQrTbody( spDoc, spTableQrTbody);  
            CHECKHRPOINTER(hr, spTableQrTbody);  
        }  
    } while (0);  
    return FAILED(hr) ? FALSE : TRUE;  
}  
[cpp]  
HRESULT CDeal12306WebPage::GetTableQrTbody( CComPtr<IHTMLDocument2> & spDoc,  
    CComPtr<IHTMLElement> & spElem )  
{  
    HRESULT hr = E_FAIL;  
    do  {  
        CComPtr<IHTMLDocument2> spMainDoc;  
        hr = GetMainDoc( spDoc, spMainDoc);  
        CHECKHRPOINTER(hr, spMainDoc);  
  
        CComPtr<IHTMLElement> spEnter_wElem;  
        hr = GetEnter_wElement(spMainDoc, spEnter_wElem );  
        CHECKHRPOINTER(hr, spEnter_wElem);  
  
        CComPtr<IHTMLElement> spForm;  
        hr = GetElementByID( spEnter_wElem, L"confirmPassenger", spForm);  
        CHECKHRPOINTER(hr, spForm);  
  
        CComPtr<IHTMLElement> spTable;  
        hr = GetElementByClassName( spForm, L"table_qr", spTable);  
        CHECKHRPOINTER(hr, spTable);  
  
        hr = GetElementByIndex( spTable, 0, spElem);  
        CHECKHRPOINTER(hr, spElem);  
    } while (0);  
    return hr;  
}  
        插入用户信息,并设置相应的选项
        我们看下用户填写信息的位置的HTML代码结构
 
        我们可以看到5个passenger可填写区域。目前只有第一个显示出来,而其他四个还没有显示。在上图的最下面是个超链接,其对应于“添加1位乘车人”按钮。可以想象,该按钮的一个操作就是将不能显示的tr显示出来。我们“人”线程填写用户信息的过程和人的行为是一致的:填写一个人信息后 ,点击“添加1位乘车人”,再填写一个……我们用代码说明这个过程。
 
[cpp]  
HRESULT CDeal12306WebPage::AddPassengerInfo( CComPtr<IHTMLElement>& spTableQrTbody,  
    const VecStSinglePassengerInfo& vecStSingleinfo )  
{  
    HRESULT hr = E_FAIL;  
    do {  
        // 下标没有从0开始!  
        int i = 1;  
        for ( VecStSinglePassengerInfoCIter it = vecStSingleinfo.begin();   
            it != vecStSingleinfo.end();i++ ) {  
                CString cstrPassengerId;  
                cstrPassengerId.Format(PASSENGERID, i);  
                hr = BookSinglePassenger( spTableQrTbody, cstrPassengerId, it);  
                CHECKHR(hr);  
  
                it++;  
                if ( it != vecStSingleinfo.end() ) {  
                    AddPassenger(spTableQrTbody);  
                }  
        }  
    } while (0);  
    return hr;  
}  
        上面代码我们将枚举用户设置的乘客信息。第12行,我们将在table中填写一个乘客信息。第16行,我们将判断最新加入的用户是否是最后一个,如果不是最后一个,则点击“添加1位乘车人”。
[cpp]  
HRESULT CDeal12306WebPage::AddPassenger( CComPtr<IHTMLElement> & spTableQrTbody )  
{  
    HRESULT hr = E_FAIL;  
    do {  
        CComPtr<IHTMLElement> spTr;  
        hr = GetElementByIndex(spTableQrTbody, 6, spTr);  
        CHECKHRPOINTER(hr, spTr);  
  
        CComPtr<IHTMLElement> spTd;  
        hr = GetElementByIndex(spTr, 1, spTd);  
        CHECKHRPOINTER(hr, spTd);  
  
        CComPtr<IHTMLElement> spA;  
        hr = GetElementByIndex(spTd, 0, spA);  
        CHECKHRPOINTER(hr, spA);  
  
        hr = spA->click();  
    } while (0);  
    return hr;  
}  
        填写每个乘客信息的代码是
[cpp]  
HRESULT CDeal12306WebPage::BookSinglePassenger( CComPtr<IHTMLElement> & spElem,   
    const CString& cstrPassengerID, VecStSinglePassengerInfoCIter iter )  
{  
    HRESULT hr = E_FAIL;  
    do  {  
        CComPtr<IHTMLElement> spTr;  
        hr = GetElementByID( spElem, cstrPassengerID, spTr );  
        CHECKHRPOINTER(hr, spTr);  
         &
补充:软件开发 , C++ ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,