Всем привет.
Сегодня расскажу как можно использовать элемент WebBrowser для написания эмуляторов человеческой активности.
Рассматривать будем на примере игры Грани реальности и напишу я простенького бота для ловли крабов.
Форма нашей программы будет такой:
Главный элемент - компонент вебброузер. Сверху панелька с anchor = top и right. И на ней 3 кнопки и 1 текстфилд. Кнопки выполняют след. ф-ции: запуск бота,
идти в город/ на место ловли. Label выполняет роль своеобразного статуса, конечно можно было сделать по другому, но мне так удобней :)
Немного теории.
Вот 2 линка, которые желательны к исследованию перед тем как пойдем дальше.
http://www.cryer.co.uk/brian/delphi/twebbrowser/twebbrowser_oleobject.htm
http://www.cryer.co.uk/brian/delphi/twebbrowser/read_write_form_elements.htm
Для того чтобы не вставлять элемент адресной строки я в функцию onShow вставил код следующего содержания:
procedure TForm1.FormShow(Sender: TObject);
begin
WebBrowser1.Navigate('http://www.ereality.ru/');
end;
Думаем дальше. Как программно определить элемент с которым взаимодействует пользователь, да ещё и нажать на него(ввести что-то)?
Для броузера Firefox есть 2 интересных надстройки: Dom inspector и Firebug.
Сравнивать я их сейчас не буду, а покажу как использовать.
Ставим FireBug и дальше так же как на картинке щелкаем на линк правой кнопкой мыши и выбираем анализировать элемент.
Внизу откроется всплывающие окошко и в нем нам будет интересно вот что:
Обратим внимание, что создатели игры не дураки, и тоже кое-что понимают. Поэтому они ввели дополнительный элемент для защиты от начинающих программистов -
вторая кнопка Ловить. Но мы можем отсортировать две кнопки, по какому-либо параметру, вернее даже по innertext/innerhtml либо outertext/outerhtml.
Вглубляться в это я не буду, смысл в том что inner - то что внутри не считая тэга, а outer все вместе с тэгом контейнером.
Вот функция для совершения клика:
Конструкция Document.Frames.Item(0).Document Указывает на то что мы берем документ первого фрейм. В конструкции данного сайта используется IFRAME который
один. В документе которого мы берем все ссылки(а), и ищем среди них ту где есть текст Крабы: Ловить и ещё эта ссылка должна содержать аттрибут name
Нажав на линк первый раз мы обломаемся - капча. Ну от капчи такого рода никуда не дется, кроме как заплатить деньги что бы взрослые дяти/тети понажимали за
вас. Здесь я должен снять шляпу перед создателями - ни графически, ни аналитически её сломать мне не удалось.
Опять же проведем процедуру с firebug, посмотрим как выглядит наша капча. Я сделал функцию - сигнализацию, которая будет кричать и вопить если появилась
капча, которая кстати содержится в форме, единственной на весь документ.
Ну вроде все. Мы начали ловить.
Но что-же делать, как определить когда нам жать кнопку достать и куда жать?
Нам придет на помощь firebug.
]
Видим что в элементе с id td_wrk(которые уникален!) имеем наши проценты и 2 кнопки: видимую и невидимую, нам надо жать видимую.
В итого пораскинув мозгами получаем вот такую вот ф-цию:
Берем позицию + и позицию % между ними текст. Вроде все просто и понятно. Если выскочит ошибка функцию отправит фалс и через некоторое время будет вызвана
опять.
Нажимаем кнопку так:
Таким образом мы получили нужные нам действия:
1. жмем на ссылку
2. если капча то кричим
3. ждем, жмем достать
Ниже полный листинг программы:
P.S.Прошу прощения за некоторые корявости. Первый блин комом. Обещаю в будущем делать все грамотно.
P.P.S. Этот материал имеет только образовательную цель. Я в эту игру не играю, а просто показываю на её примере как можно использовать элементы webbrowser. Эмуляция действий человека является мошенничеством и наказывается баном. Используйте на свой страх и риск. Прошу прощения, если нанес кому-то ущерб.
Сегодня расскажу как можно использовать элемент WebBrowser для написания эмуляторов человеческой активности.
Рассматривать будем на примере игры Грани реальности и напишу я простенького бота для ловли крабов.
Форма нашей программы будет такой:
Главный элемент - компонент вебброузер. Сверху панелька с anchor = top и right. И на ней 3 кнопки и 1 текстфилд. Кнопки выполняют след. ф-ции: запуск бота,
идти в город/ на место ловли. Label выполняет роль своеобразного статуса, конечно можно было сделать по другому, но мне так удобней :)
Немного теории.
Вот 2 линка, которые желательны к исследованию перед тем как пойдем дальше.
http://www.cryer.co.uk/brian/delphi/twebbrowser/twebbrowser_oleobject.htm
http://www.cryer.co.uk/brian/delphi/twebbrowser/read_write_form_elements.htm
Для того чтобы не вставлять элемент адресной строки я в функцию onShow вставил код следующего содержания:
procedure TForm1.FormShow(Sender: TObject);
begin
WebBrowser1.Navigate('http://www.ereality.ru/');
end;
Думаем дальше. Как программно определить элемент с которым взаимодействует пользователь, да ещё и нажать на него(ввести что-то)?
Для броузера Firefox есть 2 интересных надстройки: Dom inspector и Firebug.
Сравнивать я их сейчас не буду, а покажу как использовать.
Ставим FireBug и дальше так же как на картинке щелкаем на линк правой кнопкой мыши и выбираем анализировать элемент.
Внизу откроется всплывающие окошко и в нем нам будет интересно вот что:
Обратим внимание, что создатели игры не дураки, и тоже кое-что понимают. Поэтому они ввели дополнительный элемент для защиты от начинающих программистов -
вторая кнопка Ловить. Но мы можем отсортировать две кнопки, по какому-либо параметру, вернее даже по innertext/innerhtml либо outertext/outerhtml.
Вглубляться в это я не буду, смысл в том что inner - то что внутри не считая тэга, а outer все вместе с тэгом контейнером.
Вот функция для совершения клика:
;
procedure PressLink;
var links:OleVariant;
i:integer;
begin
links := Form1.WebBrowser1.OleObject.Document.Frames.Item(0).Document.getelementsbytagname('a');
for i := 0 to links.length-1 do
begin
if AnsiSameStr(links.item(i).innertext,'Крабы: Ловить') and (Pos('name',links.item(i).outerhtml)> 0) then
begin
links.item(i).click;
break;
end;
end;
end;
Конструкция Document.Frames.Item(0).Document Указывает на то что мы берем документ первого фрейм. В конструкции данного сайта используется IFRAME который
один. В документе которого мы берем все ссылки(а), и ищем среди них ту где есть текст Крабы: Ловить и ещё эта ссылка должна содержать аттрибут name
Нажав на линк первый раз мы обломаемся - капча. Ну от капчи такого рода никуда не дется, кроме как заплатить деньги что бы взрослые дяти/тети понажимали за
вас. Здесь я должен снять шляпу перед создателями - ни графически, ни аналитически её сломать мне не удалось.
Опять же проведем процедуру с firebug, посмотрим как выглядит наша капча. Я сделал функцию - сигнализацию, которая будет кричать и вопить если появилась
капча, которая кстати содержится в форме, единственной на весь документ.
function CheckCaptcha:Boolean;
begin
if Form1.WebBrowser1.OleObject.Document.Frames.Item(0).Document.Forms.length > 0 then
begin
Result:= False;
MessageBeep(MB_ICONHAND);
ShowWindow(Application.Handle, SW_RESTORE)
end
else
begin
Result:= True;
end;
end;
Ну вроде все. Мы начали ловить.
Но что-же делать, как определить когда нам жать кнопку достать и куда жать?
Нам придет на помощь firebug.
]
Видим что в элементе с id td_wrk(которые уникален!) имеем наши проценты и 2 кнопки: видимую и невидимую, нам надо жать видимую.
В итого пораскинув мозгами получаем вот такую вот ф-цию:
function CheckPercentage:Boolean;
var container:OleVariant;
m,k:integer;
CheckString:String;
begin
try
container := Form1.WebBrowser1.OleObject.Document.Frames.Item(0).Document.getelementbyid('td_wrk');
CheckString:=container.innertext;
m:=Pos('%',CheckString);
k:=Pos('+',CheckString);
if(m = 0) then Result:= True;
if m - k > 2 then
begin
Result:= True
end
else if (StrToInt(CheckString[m - 1]) > 0) then
begin
Result:= True
end
else
begin
Result:= False;
end
except
Result:=False;
end;
end;
Берем позицию + и позицию % между ними текст. Вроде все просто и понятно. Если выскочит ошибка функцию отправит фалс и через некоторое время будет вызвана
опять.
Нажимаем кнопку так:
procedure CatchUp;//Nazat na knopku dostat
var buttons:OleVariant;
i:integer;
begin
buttons:=Form1.WebBrowser1.OleObject.Document.Frames.Item(0).Document.getelementsbytagname('button');
for i := 0 to buttons.length-1 do
begin
if AnsiSameStr(buttons.item(i).innertext,'Достать') and (Pos('WIDTH: 90px',buttons.item(i).outerhtml)> 0) then
begin
sLog('','Lets catchup');
buttons.item(i).click;
break;
end;
end;
end;
Таким образом мы получили нужные нам действия:
1. жмем на ссылку
2. если капча то кричим
3. ждем, жмем достать
Ниже полный листинг программы:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, OleCtrls, SHDocVw, StdCtrls, MSHTML, ExtCtrls,XpMan,Math,uLog;
type
TForm1 = class(TForm)
WebBrowser1: TWebBrowser;
Panel1: TPanel;
Button4: TButton;
edt1: TEdit;
Button1: TButton;
Button2: TButton;
procedure FormShow(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure Split
(const Delimiter: Char;
Input: string;
const Strings: TStrings) ;
begin
Assert(Assigned(Strings)) ;
Strings.Clear;
Strings.Delimiter := Delimiter;
Strings.DelimitedText := Input;
end;
function CheckWeight:Boolean;//Rabotaet
var container:OleVariant;
weight:TStringList;
begin
container := Form1.WebBrowser1.OleObject.Document.getelementbyid('b_massa');
weight:= TStringList.Create;
Split('/',container.innertext,weight);
if(StrToInt(weight[0]) < StrToInt(weight[1])) then
begin
sLog('','weight is ok');
Result:= true;
end
else
begin
sLog('','weight is not ok');
Result:= false;
end;
end;
procedure delay(delay: DWORD);
var
lTicks: DWORD;
begin
lTicks := GetTickCount + delay;
repeat
Sleep(100);
Application.ProcessMessages;
until (lTicks <= GetTickCount);
end;
procedure PressLink;
var links:OleVariant;
i:integer;
begin
links := Form1.WebBrowser1.OleObject.Document.Frames.Item(0).Document.getelementsbytagname('a');
for i := 0 to links.length-1 do
begin
if AnsiSameStr(links.item(i).innertext,'Крабы: Ловить') and (Pos('name',links.item(i).outerhtml)> 0) then
begin
sLog('','Lets press link');
links.item(i).click;
break;
end;
end;
end;
function CheckCaptcha:Boolean;//Rabotaet
begin
if Form1.WebBrowser1.OleObject.Document.Frames.Item(0).Document.Forms.length > 0 then
begin
sLog('','Cap4a found');
Result:= False;
MessageBeep(MB_ICONHAND);
ShowWindow(Application.Handle, SW_RESTORE)
end
else
begin
sLog('','cap4a not found');
Result:= True;
end;
end;
function CheckPercentage:Boolean;//Rabotaet
var container:OleVariant;
m,k:integer;
CheckString:String;
begin
try
container := Form1.WebBrowser1.OleObject.Document.Frames.Item(0).Document.getelementbyid('td_wrk');
CheckString:=container.innertext;
sLog('','Percentage:this is container outerhtml');
sLog('',container.outerhtml);
sLog('','Percentage:this is container innertext');
sLog('',container.innertext);
m:=Pos('%',CheckString);
k:=Pos('+',CheckString);
if(m = 0) then Result:= True;
sLog('','Value of m:' + IntToStr(m));
sLog('','Value of k:' + IntToStr(k));
if m - k > 2 then
begin
sLog('','Percentage: number length > 1symb');
Result:= True
end
else if (StrToInt(CheckString[m - 1]) > 0) then
begin
sLog('','Percentage: number value > 0');
Result:= True
end
else
begin
sLog('','Percentage: number value = 0');
Result:= False;
end
except
sLog('','Error reading percantage');
Result:=False;
end;
end;
function CheckCage:Boolean;//Rabotaet
var container:OleVariant;
CheckString:String;
begin
container := Form1.WebBrowser1.OleObject.Document.getelementbyid('kt');
CheckString:=container.innertext;
if Pos('Ваша клетка слома',CheckString) > 0 then
begin
sLog('','Cage is broken');
Result:=False
end
else
begin
sLog('','cage is fine');
Result:=True;
end;
end;
procedure CatchUp;//Nazat na knopku dostat
var buttons:OleVariant;
i:integer;
begin
buttons:=Form1.WebBrowser1.OleObject.Document.Frames.Item(0).Document.getelementsbytagname('button');
for i := 0 to buttons.length-1 do
begin
if AnsiSameStr(buttons.item(i).innertext,'Достать') and (Pos('WIDTH: 90px',buttons.item(i).outerhtml)> 0) then
begin
sLog('','Lets catchup');
buttons.item(i).click;
break;
end;
end;
end;
function CheckMove:Boolean;//Работает
var container:OleVariant;
begin
container:=Form1.WebBrowser1.OleObject.Document.Frames.Item(0).Document.getelementbyid('p_mv_timer');
if Pos('Перемещаемся на сектор',container.innertext) > 0 then
Result:= True
else
Result:= False;
end;
procedure Move(direction:boolean); //True - gorod//false obratno //rabotaet
var i:integer;
b:boolean;
begin
If direction then
begin
for I := 0 to 7 do
begin
Form1.WebBrowser1.OleObject.Document.Frames.Item(0).Document.getelementbyid('s7').click;
repeat
delay(3000);
b:=CheckMove;
until b = False;
end;
end
else
begin
for I := 0 to 7 do
begin
Form1.WebBrowser1.OleObject.Document.Frames.Item(0).Document.getelementbyid('s3').click;
repeat
delay(1000);
b:=CheckMove;
until b = False;
end;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
Move(True);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
Move(False);
end;
procedure TForm1.Button4Click(Sender: TObject);
var b:Boolean;
begin
while AnsiSameStr(edt1.text, 'go') do
begin
Randomize;
if not CheckWeight then
begin
ShowMessage('oops');
Exit;
end;
delay(1000);
PressLink;
delay(Round(3000*Random));
delay(3000);
repeat
delay(1000);
b:= CheckCaptcha;
until b = true;
delay(1000);
if not CheckCage then
begin
ShowMessage('oops');
Exit;
end;
repeat
delay(3000);
b:= CheckPercentage;
until b = True;
delay(4000);
CatchUp;
delay(3000);
end;
end;
procedure TForm1.FormShow(Sender: TObject);
begin
WebBrowser1.Navigate('http://www.ereality.ru/');
uLog.LogFileName := ExtractFilePath(GetModuleName(HInstance))+'log.log';
uLog.LogLevel := 0;
uLog.EnableMessages:=True
end;
end.
P.S.Прошу прощения за некоторые корявости. Первый блин комом. Обещаю в будущем делать все грамотно.
P.P.S. Этот материал имеет только образовательную цель. Я в эту игру не играю, а просто показываю на её примере как можно использовать элементы webbrowser. Эмуляция действий человека является мошенничеством и наказывается баном. Используйте на свой страх и риск. Прошу прощения, если нанес кому-то ущерб.
Комментариев нет:
Отправить комментарий