领悟旧事

Learned Helplessness
分类新闻>>生活领悟>>
一次C++与JAVA的混战
来源:http://www.xx0594.com/
时间:2018-4-28
作者:  浏览人数:1011
现在,网络投票越来越多,最近经历一次网络投票,颇有收获。
    主要问题有:
    一、手机移植到PC;
    二、网页上如何实现自动化功能(包括点击、输入等);
    三、验证码识别。
    现整理如下:
    (一)手机端移植到PC
    现在网络上的投票大多是移动端,有相当一部和网站(网页)用PC打开时,其功能会受到限制。本次实站的网站就是如此。在手机端打开时,会有“点赞”、“投票”的功能,而用PC端的浏览器打开时,则只有查看的功能,无法进行投票的操作。
    针对这种情况,可以利用Chrome的Agent的功能。安装Chrome浏览器,然后安装Agent,只后Chrome浏览器即变成所设置的设备的,操作系统有Android、Ios等,设备有三星、苹果等等的Pad、Phone等,应有尽有。基本上可满足。
    但这么做也有问题,即有的网站会穿透你的Agent设置。我用这种方法,只成功过一次。
    最简单的办法就是用C++Builder 6的TCppWebBorwser。可能是由于其太落后后了,也可能是网站检测方法用if... else的缘故,该控件竟然毫无阻碍地完成了手机上的所有功能。
   (二)、网页上如何实现自动化功能
    1、最原始的方法是用SetCursorPos来设置鼠标位置,然后用mouse_event来模拟点击。
    这种方法模拟的人工的点击,可以完成任何复杂的动作,缺点是鼠标被程序占用,无法进行人工的其它操作。
    2、调用Java直接操作——这是本文的重头戏。
    经过对源网页代码的研读,我发现不论选取候选人,还是进行投票、验证码的产生,都是调用scrip里的Java产生。如果我们能调用里面的函数,问题就更简单了。经过探索,终于实现了。
    函数如下(C++):
bool __fastcall TForm1::CrnRunJavaScript(WideString sFunc)
{
    IHTMLWindow2 *pWin;
    VARIANT vRet;
    bool bRet = false;
    IHTMLDocument2 *pDoc;

    if(FAILED(CppWebBrowser1->Document->QueryInterface(IID_IHTMLDocument2, ( LPVOID* )&pDoc))) {
        return bRet;
     }
     try {
        pDoc->get_parentWindow(&pWin);
        if(pWin != NULL)
        {
        try {
            //pWin->execScript(L"showVcDiv();", L"JScript", &vRet);
            pWin->execScript(sFunc, L"JScript", &vRet);
            bRet = true;
        }
        __finally
        {
            pWin = NULL;
        }
    }
    }
    __finally
    {
    pDoc = NULL;
     }
     return bRet;
}
//---------------------------------------------------------------------------
//调用方法如下: 
AnsiString sWebInput="$(\"#vc\").val("; //查找输入框,网页的输入框ID为vc
sWebInput+=LabeledEdit1->Text+");";//设置输入框内容;
CrnRunJavaScript(WideString(sWebInput)); //调用原网页的JS函数,填入验证码。相当于Java里的$("#vc").val("我要输入");
CrnRunJavaScript(L"submitVote();"); //调用原网页的JS函数,提交投票。
 通过调用原函数,实现的网页上所有隐藏的功能,操作简单轻松,也更高效。实现这一步的关键是要认真阅读源码。特别Java函数,有的跨文件调用,用注意跟踪。同时要熟悉Java语言。如本人通过Java函数,直接选定候选人,一步到位!代码如:

        WideString sSelectName=L"var controls = document.getElementsByTagName('input'); for(var i=0; i<controls.length; i++){"
            "if(controls[i].value=='366336.400058'){controls[i].checked=true;"
            "break;}}";//选择候选人,但没有显示出来,速度更快。
        WideString sSelectAndShowName=L"var tags=$('.lx-p');"
                "for(var i=0;i<tags.length;i++){"
                "var txt =tags.eq(i);"
                " if(txt.parent().find('input').val()=='366336.400058')"
                "{txt.parent().find('input').prop('checked', true);txt.text('Selected');txt.css('background-color','#999');break;}"
                "};";//选择候选人,并显示出来,速度稍慢点。

    if(ShowSelected_ChkBox->Checked) CrnRunJavaScript(sSelectAndShowName); //如果要显示选择候选人结果。
           else   CrnRunJavaScript(sSelectName);//不显示选择候选人结果。

代码(Java)说明:
    sSelectName变量,是查找网页所有input,如果其值为366336.400058(候选人),就设置其Checked=true;
     sSelectAndShowName变量,是查找网页所有为.lx-p的元素,通过其查找父元素input,如果父元素的值为366336.400058(候选人),再设置父元素的该元素的值及属性。
   三、验证码的识别和输入
    通过上面的两步,基本实现自动化,只需要输入验证码就可以实现快速投票。经过对比,在手机上操作,一般顺利的话一分钟会投3票,要是遇到验证码输入错误,一分钟只能投1票,在电脑上,一般在8-10票。
    制约投票速度的不是网速或程序有什么问题,是该网页上验证码无法出现,有时刷一次验证码等待其出现要20多妙。如果验证码出来的速度很快的,投票速度更快的提高的。
    有什么办法可以实现验证码的识别和输入自动化呢?
    不做不知道,一做才发现,这是个目前还没有有效的解决方法。因为验证码是经过扭曲变化、加噪等处理的,人工识别起来都有点难度。
    我经过努力,基本上克服这个难题,虽然不是很有效。
    调用谷歌的Tesseract-OCR40系统。这个系统使用起来非常麻烦,网络上介绍的文章多挂一漏万,只有自己实战,才能掌握。
    其中字库的准备及训练最为关键,也是最烦的。
    编写该程序的时间大部分时间都花在这里……
    ……
    最后的结果是,如果验证码扭曲的不是很厉害,全部正确识别,如果扭曲的很厉害,如错掉1至2个数字(可惜对于验证码来说,错1个就是全错了!)。一般地,一小时也会自动投个100多票,成绩骄人,实属不易!
    可以推断,如果不是扭曲的数字,甚至汉字,识别率会大幅度地提高,甚至全对。
    
 
 
 
 
 
 
 
 

关闭窗口
 访问量:508165
任何第三方若要引用、转摘本站信息,均需征得本站书面同意,否则视为侵权。本站信息为个人观点,若因引用本站信息而产生的任何情况,均与本站无关。Email:linmutou@163.com
闽ICP备14017840号-2