如何定制一款12306抢票浏览器――处理预定页面和验证码自动识别功能(四)
, spControlElem);
hr = spControlRange->add(spControlElem);
CHECKHR(hr);
VARIANT_BOOL vbReturn = VARIANT_FALSE;
CComVariant vEmpty;
CComBSTR bstrCmd(L"Copy");
hr = spControlRange->execCommand(bstrCmd, VARIANT_FALSE, vEmpty, &vbReturn );
CHECKHR(hr);
if ( VARIANT_FALSE == vbReturn ) {
hr = E_FAIL;
break;
}
if(OpenClipboard(NULL)){
//获得剪贴板数据
HBITMAP handle = (HBITMAP)GetClipboardData(CF_BITMAP);
if ( NULL != handle ) {
CImage Img;
Img.Attach(handle);
hr = Img.Save(cstrFilePath);
}
else {
hr = E_FAIL;
}
CloseClipboard();
}
} while (0);
return hr;
}
截屏、识别、输入验证码的逻辑
[cpp]
HRESULT CDeal12306WebPage::SetCaptcha( CComPtr & spTableQrTbody )
{
HRESULT hr = E_FAIL;
do {
CComPtr spImg;
hr = GetCaptchaImgElem( spTableQrTbody, spImg);
CHECKHRPOINTER(hr, spImg);
CComPtr spInput;
hr = GetCaptchaInputElem( spTableQrTbody, spInput );
CHECKHRPOINTER(hr, spInput);
CString cstrImgPath;
cstrImgPath.Format(L"%s%d.bmp", m_cstrFloder, GetTickCount());
hr = SaveImg( spImg, cstrImgPath);
CHECKHR(hr);
CString cstrNewImgPath = cstrImgPath + ".bmp";
CBmp bmp;
bmp.SetFilePath( cstrImgPath, cstrNewImgPath );
if ( FALSE == bmp.DealBmp() ) {
hr = E_FAIL;
break;
}
CString cstrTxet;
if ( FALSE == m_ocr.GetText( cstrNewImgPath, cstrTxet) ) {
hr = E_FAIL;
break;
}
if ( CAPTCHACOUNT > cstrTxet.GetLength() ) {
hr = E_FAIL;
break;
}
cstrTxet = cstrTxet.Left(CAPTCHACOUNT);
CComPtr spInputElem;
hr = spInput->QueryInterface(IID_IHTMLInputElement, (LPVOID*)&spInputElem);
CHECKHRPOINTER(hr, spInputElem);
hr = spInputElem->put_value( CComBSTR(cstrTxet.GetString()) );
CHECKHR(hr);
} while (0);
return hr;
}
如果识别的字符数不对,则会认为失败,这样我们会刷新验证码,并重新识别。
[cpp]
HRESULT CDeal12306WebPage::SetCaptchaEx( CComPtr& spTableQrTbody )
{
HRESULT hr = E_FAIL;
do {
for ( int n = 0; n < CAPTCHARETRYCOUNT; n++ ) {
hr = SetCaptcha( spTableQrTbody );
if ( FAILED(hr) ) {
// 如果失败刷新验证码再来一次
CComPtr spImg;
hr = GetCaptchaImgElem( spTableQrTbody, spImg);
CHECKHRPOINTER(hr, spImg);
spImg->click();
Sleep(CAPTCHAWAITTIME);
}
else {
break;
}
}
} while (0);
return hr;
}
验证码输入完毕后,我们将点击“提交订单”按钮。现在有个问题冒出来了:如果我们验证码输入错误,那么网页会alert一下提示“验证码错误”,这个迫使我们得去点击这个按钮。如何去点击这个按钮呢?这个问题困扰了我一下,最后我决定还是绕过这个问题——彻底屏蔽Alert弹框,并记录Alert准备弹出的内容。在点击完按钮后,我将根据保存的Alert准备弹出的内容判断是否成功和失败。
屏蔽Alert
我们的窗口要继承IDocHostShowUI接口,并修改该接口的一个方法:
[cpp]
STDMETHODIMP CBrowserHost::ShowMessage(
/* [in] */ HWND hwnd,
/* [annotation][in] */ __in __nullterminated LPOLESTR lpstrText,
/* [annotation][in] */ __in __nullterm