分享
 
 
 

报名机器人

王朝delphi·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

报名机器人

昨天帮人报一个参加日语能力考试的朋友报名,无奈报名比较火暴,到处名额已满,需要不断重试碰运气。想到本科的时候,老师组织我们去上机,结果是帮人报TOFEL的名,那场景,如打仗一般,大家先对表,精确到秒。先把表单的数据填好,等时间一到,马上按提交按钮。早了不行,要重定向回来充填好几项数据耽误时间,晚了也不行,要不就是报满,要不就是服务器负荷太重处理不过来。记得当时前后花了半个小时,每人发了30元的报酬,看了报名还是一种待遇不错的劳动,也许以后会出现不少职业的代报名公司或个人。

手工操作几次,像一般的注册或报名程序一样,没报成功要重定向回来,有几项填写的结果(如密码框)会被清掉,重试还得重填,很麻烦,就决定做一个机器人试试,于是翻出了去年做的一个投票机器人(见《一个简单的投票机器人》)。

看了一下,原来的投票页面做得很业余,就一个ASP页面,没有用户注册和IP限制,完全的匿名投票。而这个报名程序看来是花了一定心思的,有5个(根据页面的代码猜的,因为没有成功,只看到前面的三个)步骤(JSP页面),更麻烦的是几个步骤后会弹出对话框(这大大增加了难度,后面会描述解决办法)。因此不能想投票机器人那样简单的构造页面模拟提交,要想别的办法。

还是轻车熟路,用Delphi的Webbrowser控件开发。

首先就是决定不再在本地生成临时页面,而是直接打开它的页面。因为试过想跳过前面两个无关紧要的步骤而直接提交关键的第三步,但发现它检查Cookie,本地无法生成匹配的Cookie,也无法跳过,只好从头开始。

然后自动填写表单。

为了保证灵活性,表单要填的数据保存在一个XML文件中。

表格 1

读如要填数据的XML文件:

procedure TfrmMain.readInfo;

var

// xmlDom1: TXMLDocument;

Nroot,Nentry,NsubEntry:IXMLNode;

filePath : string;

i:integer;

begin

filePath := ExtractFilePath(Application.ExeName) + 'infor.xml';

try

xmlDom1.LoadFromFile(filePath);

except

on e:exception do

showmessage(e.Message);

end;

Nroot:=xmldom1.DocumentElement;

Nentry:= Nroot.ChildNodes['level'];

level := Nentry.NodeValue;

Nentry:= Nroot.ChildNodes['ID'];

id := Nentry.NodeValue;

Nentry:= Nroot.ChildNodes['pwd'];

pwd := Nentry.NodeValue;

Nentry:= Nroot.ChildNodes['sex'];

sex := Nentry.NodeValue;

Nentry:= Nroot.ChildNodes['sr'];

sr := Nentry.NodeValue;

Nentry:= Nroot.ChildNodes['cFirstName'];

cFirstName := Nentry.NodeValue;

Nentry:= Nroot.ChildNodes['cLastName'];

cLastName := Nentry.NodeValue;

Nentry:= Nroot.ChildNodes['eFirstName'];

eFirstName := Nentry.NodeValue;

Nentry:= Nroot.ChildNodes['eLastName'];

eLastName := Nentry.NodeValue;

Nentry:= Nroot.ChildNodes['question'];

question := Nentry.NodeValue;

Nentry:= Nroot.ChildNodes['answer'];

answer := Nentry.NodeValue;

Nentry:= Nroot.ChildNodes['places'];

placeNum := Nentry.ChildNodes.Count;

for i := 1 to placeNum do

begin

places[i] := Nentry.ChildNodes[i-1].NodeValue;

placesID[i] := strtoint(Nentry.ChildNodes[i-1].NodeValue);

end;

end;

用读入的数据填写第一步的表单。

表格 2

procedure TfrmMain.FillForm1;

var

idInput:IHTMLInputElement;

pinInput:IHTMLInputElement;

doc: ihtmldocument2;

begin

doc:=(WebBrowser1.Document as IHTMLDocument2);

idInput := (doc.all.item('user_name',0) as IHTMLInputElement) ;

idInput.value := id;

pinInput := (doc.all.item('pin',0) as IHTMLInputElement) ;

pinInput.value := pwd;

end;

注意填表单的时机,是在页面下载完毕以后,由webbrowser的DocumentComplete事件触发。填完表单后马上模拟点击Submit按钮,进入第二步。

表格 3

procedure TfrmMain.WebBrowser1DocumentComplete(Sender: TObject;

const pDisp: IDispatch; var URL: OleVariant);

var

kk:hwnd;

obj:OleVariant;

doc: ihtmldocument2;

begin

if (stage = 0) then //第一步

begin

FillForm1; //填表单1

stage := stage +1;

doc:=(WebBrowser1.Document as IHTMLDocument2);

obj:=doc.all.item('Submit',0);

obj.click; //点“下一步”按钮

statusBar1.Panels[0].Text := '正在打开报名协议页面。。。';

end

else if (stage = 1) then //第二步

begin

//showmessage(inttostr(stage) + ' WebBrowser1DocumentComplete');

doc:=(WebBrowser1.Document as IHTMLDocument2);

obj:=doc.all.item('Agree',0);

obj.click;

stage := stage +1;

end

else if (stage = 2) then //第三步

begin

FillForm2; //填表单2

TryAgain; //报名一次

timer1.Enabled := true;

timer1.Interval := strtoint(edtInterval.Text) * 1000;

stage := stage +1;

statusBar1.Panels[0].Text := '正在报名。。。';

end

else if (stage >= 3) then

begin

if (isRun) then

begin

TryAgain;

stage := stage +1;

end;

end

end;

第一步后,会弹出一个对话框,确定后才进入第二步,因为只有一次,这里没有处理,由手工点击确定。

第二步比较简单,一个协议条款,直接模拟点击“同意”按钮,进入第三步。

第三步是关键步骤,因为报名信息都在这里填,并提交。首先用读入的XML中的数据填第二个表单,然后提交表单。并启动一个定时器,定时提交表单重复尝试报名。

表格 4

定时器重复报名:

procedure TfrmMain.Timer1Timer(Sender: TObject);

var

doc: ihtmldocument2;

placeSelect:IHTMLSelectElement;

pwd1Input:IHTMLInputElement;

begin

TryAgain;

Application.ProcessMessages;

end;

每次报名希望重试不同的考点,以扩大选择的范围,因此重复时轮流用选择的几个考点报名:

表格 5

procedure TfrmMain.TryAgain;

var

doc: ihtmldocument2;

placeSelect:IHTMLSelectElement;

pwd1Input:IHTMLInputElement;

kk:hwnd;

begin

if (webbrowser1.LocationURL = url3) then

begin

doc:=(WebBrowser1.Document as IHTMLDocument2);

placeSelect := (doc.all.item('tp_cname',0) as IHTMLSelectElement) ;

placeSelect.selectedIndex := placesID[(times mod placeNum) + 1]; //轮流换考点

pwd1Input := (doc.all.item('pwd1',0) as IHTMLInputElement) ;

pwd1Input.value := pwd;

submitForm;

times := times + 1;

statusBar1.Panels[0].Text := '正在第' + inttostr(times) + '次报名。。。';

Application.ProcessMessages;

end

else //报名成功,报名成功,我也不知道成功是什么样子,只好根据页面地址判断

begin

timer1.Enabled := false;

btnReg.Caption := '开始';

isRun := false;

statusBar1.Panels[0].Text := '报名已成功。。。';

showmessage('报名成功!!!!!!!!!!!!');

end;

end;

在重复报名中遇到一个问题:报名不成功会弹出一个对话框,然后页面阻塞在那里,无法进行下去。没有办法,只有再起一个进程,找到IE弹出的对话框,强行关掉。(其实关掉并不是最好的办法,如果能发送一个消息点击确定按钮最好,可惜没找到相关资料)。

表格 6

procedure TfrmMain.NewThread;

var

hThread:Thandle;//定义一个句柄

ThreadID:DWord;

begin

//创建线程,同时线程函数被调用

//messagebox(Handle,'创建线程',nil,MB_OK);

hthread:=CreateThread(nil,0,@ClosePopDialog,nil,0,ThreadID);

if hThread=0 then

messagebox(Handle,'创建线程失败',nil,MB_OK);

end;

function ClosePopDialog(P:pointer):Longint;stdcall;

var

i:longint;

DC:HDC;

kk:hwnd;

begin

while (true) do

begin

if ((frmMain.stage = 3) ) then

begin

kk := findwindow(nil,'Microsoft Internet Explorer');

if kk<>0 then //如果找到IE弹出对话框,就干掉它

begin

setActiveWindow(kk);

sendmessage(kk,wm_close,0,0);

end

end;

sleep(5000);

end;

end;

图表 1 主界面

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有