DDrim
15.01.2013, 22:23
Здравствуйте! Делаю бота для игра Варвары (на этом форуме есть несколько тем по данной игре).
Бота делаю на компонентах Indy: IdHTTP + TIdCookieManager.
Все вроде бы отлично, бот успешно авторизируется, переходит почти по всем ссылкам.
Но вот проблема: при заходе к конкретному дракону (кто играл, тот поймет), на странице есть ссылка "Встать в очередь". Да к вот эта ссылка почему-то не нажимается (делаю GET-запрос). Т.е. возвращается страница, в которой ссылка "Встать в очередь" просто не нажата. Ответ сервера - 200 ОК.
Никак не могу понять, в чем дело. Ссылка "Встать в очередь" парситься точно правильно...
Вот мини-пример бота, который авторизируется в игре, переходит к дракону и пытается встать в очередь на его убийство.
const
Barbars = '[Ссылки могут видеть только зарегистрированные и активированные пользователи]';
var
Form1: TForm1;
CurrentURL: AnsiString; // Текущая ссылка (где бот сейчас "находится")
Code: AnsiString; // Весь html-код игры, который постоянно меняется
implementation
{$R *.dfm}
function Get2LinkTo1(ALink_1, ALink_2: AnsiString): AnsiString;
var
i: Integer;
begin
Result := '';
if(ALink_1 = '') and (ALink_2 = '') then Exit;
if(ALink_2 = '') then begin
Result := ALink_1;
Exit;
end;
if(ALink_1 = '') then begin
Result := ALink_2;
Exit;
end;
if(Copy(ALink_1, Length(ALink_1), 1) = '/') then
ALink_1 := Copy(ALink_1, 1, Length(ALink_1) - Length('/'));
While(Copy(ALink_2, 1, Length('../')) = '../') do begin
for i:=Length(ALink_1) downto 1 do begin
if(Copy(ALink_1, i, 1) <> '/') then Continue;
ALink_1 := Copy(ALink_1, 1, i - 1);
Break;
end;
Delete(ALink_2, 1, Length('../'));
end;
ALink_1 := ALink_1 + '/';
Result := ALink_1 + ALink_2;
end;
procedure GET_Link(aLink: AnsiString);
var
MS :TMemoryStream;
ResHTML: TStringList;
begin
if(aLink = '') then Exit;
MS := TMemoryStream.Create;
ResHTML := TStringList.Create;
Try
form1.Id[Ссылки могут видеть только зарегистрированные и активированные пользователи](aLink, MS);
CurrentURL := aLink;
MS.Seek(0, 0);
ResHTML.LoadFromStream(MS);
Except
on e : EID[Ссылки могут видеть только зарегистрированные и активированные пользователи] do Begin
if form1.Id[Ссылки могут видеть только зарегистрированные и активированные пользователи] = 302 then begin
try
// получаем новый адрес - адрес перенаправления
CurrentURL := form1.Id[Ссылки могут видеть только зарегистрированные и активированные пользователи]
form1.Id[Ссылки могут видеть только зарегистрированные и активированные пользователи](CurrentURL, MS);
MS.Seek(0, 0);
ResHTML.LoadFromStream(MS);
except
on e:Exception do
// предусматриваем, что исключение может возникнуть и тут
ShowMessage('Ошибка при получении нового адреса.'+e.Message);
end;
end
else
//http 404, 501 и так далее
ShowMessage('Ошибка другого вида, не 302:'+e.Message);
end;
on e:Exception do
ShowMessage('Ошибка: ' + e.Message);
end;
Code := Utf8ToAnsi(ResHTML.Text);
end;
procedure InitBot(aLogin, aPassword: AnsiString);
var
Data: TStringList;
begin
Data := TStringList.Create;
with form1 do begin
Id[Ссылки могут видеть только зарегистрированные и активированные пользователи] := True;
Id[Ссылки могут видеть только зарегистрированные и активированные пользователи] := IdCookieManager1;
Id[Ссылки могут видеть только зарегистрированные и активированные пользователи] := True;
Id[Ссылки могут видеть только зарегистрированные и активированные пользователи] := 'barbars.ru';
Id[Ссылки могут видеть только зарегистрированные и активированные пользователи] := 'Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.10.229 Version/11.61';
Id[Ссылки могут видеть только зарегистрированные и активированные пользователи] := 'application/x-[Ссылки могут видеть только зарегистрированные и активированные пользователи]';
Id[Ссылки могут видеть только зарегистрированные и активированные пользователи] := 'text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1';
Id[Ссылки могут видеть только зарегистрированные и активированные пользователи] := 'ru-RU,ru;q=0.9,en;q=0.8';
Id[Ссылки могут видеть только зарегистрированные и активированные пользователи] := 'windows-1251,utf-8;q=0.7,*;q=0.7';
Id[Ссылки могут видеть только зарегистрированные и активированные пользователи] := Barbars;
CurrentURL := Barbars;
end;
Data.Add('id1_hf_0');
Data.Add('login=' + aLogin);
Data.Add('password=' + aPassword);
Try // Авторизируюсь:
// Если логин или пароль не подходят:
if(AnsiPos('Неверный ник или пароль', Utf8ToAnsi(Form1.Id[Ссылки могут видеть только зарегистрированные и активированные пользователи]('[Ссылки могут видеть только зарегистрированные и активированные пользователи]', Data))) > 0) then begin
// raise Exception.Create('Ошибка! Логин или пароль не подходят!' + #10#13 + 'Бот может работать не корректно!');
end;
CurrentURL := '[Ссылки могут видеть только зарегистрированные и активированные пользователи]';
Except
on e : EID[Ссылки могут видеть только зарегистрированные и активированные пользователи] do Begin
if e.ReplyErrorCode = 302 then begin
try
// получаем новый адрес - адрес перенаправления
CurrentURL := form1.Id[Ссылки могут видеть только зарегистрированные и активированные пользователи]
form1.Id[Ссылки могут видеть только зарегистрированные и активированные пользователи](CurrentURL);
except
on e:Exception do
// предусматриваем, что исключение может возникнуть и тут
ShowMessage('Ошибка при получении нового адреса.'+e.Message);
end;
end
else
//http 404, 501 и так далее
ShowMessage('Ошибка другого вида, не 302:'+e.Message);
end;
on e:Exception do
ShowMessage('Ошибка: ' + e.Message);
end;
Data.Free;
end;
function ParsLinks(aNameLink: AnsiString; aHTMLCode: AnsiString): AnsiString;
var
PosLink: Integer;
i: Integer;
begin
Result := '';
if(aNameLink = '') or (aHTMLCode = '') then Exit;
if(aNameLink = 'Пещерный стражник') then
with tstringlist.Create do free;
PosLink := AnsiPos(aNameLink, aHTMLCode);
if(PosLink <= 0) then Exit;
i := PosLink - 1;
while(Copy(aHTMLCode, i, Length('="')) <> '="') do dec(i); // Нахожу индекс знаков =" перед ссылкой
Result := Copy(aHTMLCode, i + Length('="'), PosEx('">', aHTMLCode, i + 1) - i - Length('="'));
end;
procedure CheckGame;
var
BufLinkDragon: AnsiString; // Динамическая ссылка на драконов
begin
GET_Link(Barbars);
BufLinkDragon := ParsLinks('Пещеры и драконы', Code); // Вытаскиваем "вторую часть" ссылки
BufLinkDragon := Get2LinkTo1(CurrentURL, BufLinkDragon); // Получаем полную ссылку на драконов
GET_Link(BufLinkDragon); // Переходим по ссылке на драконов
BufLinkDragon := ParsLinks('Пещерный стражник', Code); // Вытаскиваем "вторую часть" ссылки
BufLinkDragon := Get2LinkTo1(CurrentURL, '../' + BufLinkDragon); // Получаем полную ссылку на нужного дракона
GET_Link(BufLinkDragon); // Переходим по ссылке дракона
// Нажимаем на ссылку "Встать в очередь":
if(AnsiPos('Встать в очередь', Code) <= 0) then begin
showmessage('дракон мертв!');
exit;
end;
BufLinkDragon := ParsLinks('Встать в очередь', Code);
BufLinkDragon := Get2LinkTo1(CurrentURL, '../' + BufLinkDragon);
GET_Link(BufLinkDragon); // ВОТ ТУТ на ссылку бот почему-то не нажимает (ссылка точно правильная!)
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
InitBot(Edit1.Text, Edit2.Text); // Авторизируемся...
// Перехожу на главную страницу:
GET_Link(Barbars);
CheckGame; // Делаю проверку на драконов, поля и т.д.
end;
ЗЫ логин-пароль для теста не прилагаю, т.к. у меня только один аккаунт (и он основной).
Просто хотел бы понять причину, почему все ссылки нажимаются правильно, а именно ОДНА нет...
Добавлено через 8 минут
Если кто захотел скомпилировать код:
Код выше для Делфи 7.
Для Indy 9-10 (новые версии компонент) надо изменить ReplyErrorCode на ErrorCode и все отлично скомпилируется.
Бота делаю на компонентах Indy: IdHTTP + TIdCookieManager.
Все вроде бы отлично, бот успешно авторизируется, переходит почти по всем ссылкам.
Но вот проблема: при заходе к конкретному дракону (кто играл, тот поймет), на странице есть ссылка "Встать в очередь". Да к вот эта ссылка почему-то не нажимается (делаю GET-запрос). Т.е. возвращается страница, в которой ссылка "Встать в очередь" просто не нажата. Ответ сервера - 200 ОК.
Никак не могу понять, в чем дело. Ссылка "Встать в очередь" парситься точно правильно...
Вот мини-пример бота, который авторизируется в игре, переходит к дракону и пытается встать в очередь на его убийство.
const
Barbars = '[Ссылки могут видеть только зарегистрированные и активированные пользователи]';
var
Form1: TForm1;
CurrentURL: AnsiString; // Текущая ссылка (где бот сейчас "находится")
Code: AnsiString; // Весь html-код игры, который постоянно меняется
implementation
{$R *.dfm}
function Get2LinkTo1(ALink_1, ALink_2: AnsiString): AnsiString;
var
i: Integer;
begin
Result := '';
if(ALink_1 = '') and (ALink_2 = '') then Exit;
if(ALink_2 = '') then begin
Result := ALink_1;
Exit;
end;
if(ALink_1 = '') then begin
Result := ALink_2;
Exit;
end;
if(Copy(ALink_1, Length(ALink_1), 1) = '/') then
ALink_1 := Copy(ALink_1, 1, Length(ALink_1) - Length('/'));
While(Copy(ALink_2, 1, Length('../')) = '../') do begin
for i:=Length(ALink_1) downto 1 do begin
if(Copy(ALink_1, i, 1) <> '/') then Continue;
ALink_1 := Copy(ALink_1, 1, i - 1);
Break;
end;
Delete(ALink_2, 1, Length('../'));
end;
ALink_1 := ALink_1 + '/';
Result := ALink_1 + ALink_2;
end;
procedure GET_Link(aLink: AnsiString);
var
MS :TMemoryStream;
ResHTML: TStringList;
begin
if(aLink = '') then Exit;
MS := TMemoryStream.Create;
ResHTML := TStringList.Create;
Try
form1.Id[Ссылки могут видеть только зарегистрированные и активированные пользователи](aLink, MS);
CurrentURL := aLink;
MS.Seek(0, 0);
ResHTML.LoadFromStream(MS);
Except
on e : EID[Ссылки могут видеть только зарегистрированные и активированные пользователи] do Begin
if form1.Id[Ссылки могут видеть только зарегистрированные и активированные пользователи] = 302 then begin
try
// получаем новый адрес - адрес перенаправления
CurrentURL := form1.Id[Ссылки могут видеть только зарегистрированные и активированные пользователи]
form1.Id[Ссылки могут видеть только зарегистрированные и активированные пользователи](CurrentURL, MS);
MS.Seek(0, 0);
ResHTML.LoadFromStream(MS);
except
on e:Exception do
// предусматриваем, что исключение может возникнуть и тут
ShowMessage('Ошибка при получении нового адреса.'+e.Message);
end;
end
else
//http 404, 501 и так далее
ShowMessage('Ошибка другого вида, не 302:'+e.Message);
end;
on e:Exception do
ShowMessage('Ошибка: ' + e.Message);
end;
Code := Utf8ToAnsi(ResHTML.Text);
end;
procedure InitBot(aLogin, aPassword: AnsiString);
var
Data: TStringList;
begin
Data := TStringList.Create;
with form1 do begin
Id[Ссылки могут видеть только зарегистрированные и активированные пользователи] := True;
Id[Ссылки могут видеть только зарегистрированные и активированные пользователи] := IdCookieManager1;
Id[Ссылки могут видеть только зарегистрированные и активированные пользователи] := True;
Id[Ссылки могут видеть только зарегистрированные и активированные пользователи] := 'barbars.ru';
Id[Ссылки могут видеть только зарегистрированные и активированные пользователи] := 'Opera/9.80 (Windows NT 6.1; U; ru) Presto/2.10.229 Version/11.61';
Id[Ссылки могут видеть только зарегистрированные и активированные пользователи] := 'application/x-[Ссылки могут видеть только зарегистрированные и активированные пользователи]';
Id[Ссылки могут видеть только зарегистрированные и активированные пользователи] := 'text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1';
Id[Ссылки могут видеть только зарегистрированные и активированные пользователи] := 'ru-RU,ru;q=0.9,en;q=0.8';
Id[Ссылки могут видеть только зарегистрированные и активированные пользователи] := 'windows-1251,utf-8;q=0.7,*;q=0.7';
Id[Ссылки могут видеть только зарегистрированные и активированные пользователи] := Barbars;
CurrentURL := Barbars;
end;
Data.Add('id1_hf_0');
Data.Add('login=' + aLogin);
Data.Add('password=' + aPassword);
Try // Авторизируюсь:
// Если логин или пароль не подходят:
if(AnsiPos('Неверный ник или пароль', Utf8ToAnsi(Form1.Id[Ссылки могут видеть только зарегистрированные и активированные пользователи]('[Ссылки могут видеть только зарегистрированные и активированные пользователи]', Data))) > 0) then begin
// raise Exception.Create('Ошибка! Логин или пароль не подходят!' + #10#13 + 'Бот может работать не корректно!');
end;
CurrentURL := '[Ссылки могут видеть только зарегистрированные и активированные пользователи]';
Except
on e : EID[Ссылки могут видеть только зарегистрированные и активированные пользователи] do Begin
if e.ReplyErrorCode = 302 then begin
try
// получаем новый адрес - адрес перенаправления
CurrentURL := form1.Id[Ссылки могут видеть только зарегистрированные и активированные пользователи]
form1.Id[Ссылки могут видеть только зарегистрированные и активированные пользователи](CurrentURL);
except
on e:Exception do
// предусматриваем, что исключение может возникнуть и тут
ShowMessage('Ошибка при получении нового адреса.'+e.Message);
end;
end
else
//http 404, 501 и так далее
ShowMessage('Ошибка другого вида, не 302:'+e.Message);
end;
on e:Exception do
ShowMessage('Ошибка: ' + e.Message);
end;
Data.Free;
end;
function ParsLinks(aNameLink: AnsiString; aHTMLCode: AnsiString): AnsiString;
var
PosLink: Integer;
i: Integer;
begin
Result := '';
if(aNameLink = '') or (aHTMLCode = '') then Exit;
if(aNameLink = 'Пещерный стражник') then
with tstringlist.Create do free;
PosLink := AnsiPos(aNameLink, aHTMLCode);
if(PosLink <= 0) then Exit;
i := PosLink - 1;
while(Copy(aHTMLCode, i, Length('="')) <> '="') do dec(i); // Нахожу индекс знаков =" перед ссылкой
Result := Copy(aHTMLCode, i + Length('="'), PosEx('">', aHTMLCode, i + 1) - i - Length('="'));
end;
procedure CheckGame;
var
BufLinkDragon: AnsiString; // Динамическая ссылка на драконов
begin
GET_Link(Barbars);
BufLinkDragon := ParsLinks('Пещеры и драконы', Code); // Вытаскиваем "вторую часть" ссылки
BufLinkDragon := Get2LinkTo1(CurrentURL, BufLinkDragon); // Получаем полную ссылку на драконов
GET_Link(BufLinkDragon); // Переходим по ссылке на драконов
BufLinkDragon := ParsLinks('Пещерный стражник', Code); // Вытаскиваем "вторую часть" ссылки
BufLinkDragon := Get2LinkTo1(CurrentURL, '../' + BufLinkDragon); // Получаем полную ссылку на нужного дракона
GET_Link(BufLinkDragon); // Переходим по ссылке дракона
// Нажимаем на ссылку "Встать в очередь":
if(AnsiPos('Встать в очередь', Code) <= 0) then begin
showmessage('дракон мертв!');
exit;
end;
BufLinkDragon := ParsLinks('Встать в очередь', Code);
BufLinkDragon := Get2LinkTo1(CurrentURL, '../' + BufLinkDragon);
GET_Link(BufLinkDragon); // ВОТ ТУТ на ссылку бот почему-то не нажимает (ссылка точно правильная!)
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
InitBot(Edit1.Text, Edit2.Text); // Авторизируемся...
// Перехожу на главную страницу:
GET_Link(Barbars);
CheckGame; // Делаю проверку на драконов, поля и т.д.
end;
ЗЫ логин-пароль для теста не прилагаю, т.к. у меня только один аккаунт (и он основной).
Просто хотел бы понять причину, почему все ссылки нажимаются правильно, а именно ОДНА нет...
Добавлено через 8 минут
Если кто захотел скомпилировать код:
Код выше для Делфи 7.
Для Indy 9-10 (новые версии компонент) надо изменить ReplyErrorCode на ErrorCode и все отлично скомпилируется.