Мастера DELPHI, Delphi programming community Рейтинг@Mail.ru Титульная страница Поиск, карта сайта Написать письмо 
| Новости |
Новости сайта
Поиск |
Поиск по лучшим сайтам о Delphi
FAQ |
Огромная база часто задаваемых вопросов и, конечно же, ответы к ним ;)
Статьи |
Подборка статей на самые разные темы. Все о DELPHI
Книги |
Новинки книжного рынка
Новости VCL
Обзор свежих компонент со всего мира, по-русски!
|
| Форумы
Здесь вы можете задать свой вопрос и наверняка получите ответ
| ЧАТ |
Место для общения :)
Орешник |
Коллекция курьезных вопросов из форумов
KOL и MCK |
KOL и MCK - Компактные программы на Delphi
Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / rsdn.org

 
Чтобы не потерять эту дискуссию, сделайте закладку « предыдущая ветвь | форум | следующая ветвь »

Авторизация в Alpari через TWebBrowser или TChromium


TraderProg ©   (12.03.18 22:06

Здравствуйте! Столкнулся с такой проблемой. Не получается авторизоваться программно в Alpari через браузеры-компоненты Delphi, такие как TWebBrowser или TChromium. Надо заполнить логин и пароль и нажать кнопку для подключения.

Адрес страницы авторизации такой: https://alpari.com/ru/login/

Внимание! После нескольких попыток входа в течение короткого промежутка времени - появляется окно для ввода капчи. Мне на окно ввода капчи "фиолетово", так как цель - авторизоваться с первой попытки раз в сутки, используя свой логин и пароль.

Селектор DOM поля ввода текста для логина:
#authorization_login
либо такой:
body > div.page__main > div > form > div > div.grid__row.form__section.s_p_0 > div.grid__col.grid__col_w_17 > div:nth-child(1) > div.grid__col.grid__col_w_10 > div.js-form-el-holder.input.grid__col_w_4.input_focus_yes

Селектор DOM для пароля:
#authorization_password
либо такой:
body > div.page__main > div > form > div > div.grid__row.form__section.s_p_0 > div.grid__col.grid__col_w_17 > div.js-form-el-field.field.grid__row.form__section.s_pb_9.field_active > div.grid__col.grid__col_w_10 > div.js-form-el-holder.input.grid__col_w_4.input_focus_yes

Селектор кнопки "Войти":
body > div.page__main > div > form > div > div.grid__row.form__section.s_p_0 > div.grid__col.grid__col_w_17 > div:nth-child(4) > div > button

На счет кнопки "Войти" думаю проблем не должно быть, но я до проверки работы клика на нее еще не дошел - у меня не получается ввести нужный текст в поля ввода. Вылазят ошибки.


Redmond   (13.03.18 18:30[1]

На текущей машине нету Делфи, посмотреть не смогу, но в Google Chrome вроде бы вполне работают такие букмарклеты:

javascript:(function(){   document.getElementById('authorization_login').value='1234';   })();

javascript:(function(){   document.getElementById('authorization_password').value='5678';   })();

javascript:(function(){   document.getElementsByName('send')[0].style='border:solid red 6px';   })();


TraderProg ©   (13.03.18 19:32[2]

Спасибо, Redmond, опробую твой код и напишу получилось или нет. Вопрос: бумарклет - это что? прям в браузере набивается что ли? через F12 ?


TraderProg ©   (13.03.18 21:31[3]

Я пока первую версию на основе WebBrowser делаю, а на Хромиуме (где можно исполнять любой javascript код) завтра попробую.
Пока попробовал такой код:
WebBrowser1.OleObject.Document.GetElementById('authorization_login').value:='123 456';
WebBrowser1.OleObject.Document.GetElementById('authorization_password').value:=' 789321';

Текст действительно вставляется в поля, но при нажатии на кнопку вылазит предупреждение, что поля логин и пароль должны быть заполненными, НО!!! стоит только разок по любому из полей кликнуть мышкой, так сразу для системы текст в полях становится виден и запускается процесс входа в личный кабинет. В общем странный глюк. Хотя может быть каким-то таким же способом реализовать клик по полю, но мои попытки приводили только к ругани системы.

По поводу кнопки дело еще хуже. Оба моих варианта кода приводят к сообщению об ошибке.
1-й вариант:
 st:='body > div.page__main > div > form > div > div.grid__row.form__section.s_p_0 > div.grid__col.grid__col_w_17 > div:nth-child(4) > div > button';
 List:=Doc.querySelectorAll(st);
 Node:=List.item(0);
 Node.click;

Приводит к сообщению "invalid variant operation". Кстати чтобы такое сообщение не вылазило при потере объекта DOM, достаточно код вставить в блок try..except или надо что-то другое?

2-й вариант нажатия на кнопку:
WebBrowser1.OleObject.Document.getElementsByName('send').click;

Приводит к сообщению "Method 'click' not supported by automation object".


Redmond   (13.03.18 22:44[4]

Букмарклет это когда в браузере сначала делаешь вроде как закладку, но потом вместо URL указываешь протокол "javascript" а дальше код на JS: https://ru.wikipedia.org/wiki/Букмарклет
И если тыкать мышкой в закладку - тогда просто тот скрипт выполняется на текущей вкладке.

> 2-й вариант ...

Там же getElements - список там возвращается, у списка разумеется нету метода "click". С:

> Текст действительно вставляется в поля, но при нажатии на кнопку вылазит предупреждение

а... Вот про что речь. Иногда на элементах внутри FORM навешаны проверки вводимых данных, которые могут мешать (вернее не замечать что что-то изменилось). Видимо такой случай.
Первое что стоит пытаться в таких случаях - сперва ставить фокус на элемент который будем заполнять.

А вот "invalid variant operation" уже странно, на какой точно строке вылетает?


Redmond   (14.03.18 01:04[5]

Ну вот я дома. Скопировал ваш код №1. У вас выдаёт "invalid variant operation" потому что в List ноль элементов. А вы оттуда взяли Node.
И при обращении к Node... гм... Вообще мне казалось должно было вылетать ещё при попытке получить несуществующий элемент. Но как оказалось - оно молча возвращает NULL.
Я же вам уже писал что как бы надо бы делать проверки "сколько элементов в списке" и на "пустоту". Как минимум точные место и причина ошибки будет видна как на ладонях.

Старайтесь что ли обходиться без каких-либо ":nth-child(n)", как правило подобное слишком непостоянно.

З.Ы.Node.focus();
Node.value:='...';
Doc.body.focus();


Redmond   (14.03.18 03:17[6]

Ну как-то типа так:
Procedure TForm1.ToolButton5Click(Sender: TObject);
Var i: Integer; Doc, Node, List: Variant;
Begin
Doc:=WebBrowser1.Document;
/////////////////////////////////////////////////////////////////////////////////// Login Input
Node:=Doc.getElementById('authorization_login');
If IsVariantNULL(Node) Then Raise Exception.Create('Input "Login" was not found!');
Node.focus();
Node.value:='login';
Doc.body.focus();
/////////////////////////////////////////////////////////////////////////////////// Password Input
Node:=Doc.getElementById('authorization_password');
If IsVariantNULL(Node) Then Raise Exception.Create('Input "Password" was not found!');
Node.focus();
Node.value:='password';
Doc.body.focus();
/////////////////////////////////////////////////////////////////////////////////// Captcha Input
Node:=Doc.getElementById('captcha');
If IsVariantNULL(Node) Then Raise Exception.Create('Input "Captcha" was not found!');
Node.focus;
Node.value:='12345';
Doc.body.focus;
/////////////////////////////////////////////////////////////////////////////////// Submit Button
List:=Doc.getElementsByName('send');
Node:=List.item(0);
If IsVariantNULL(Node) Then Raise Exception.Create('Button "Submit" was not found!');
Node.focus();
Application.ProcessMessages();
Node.click();
///////////////////////////////////////////////////////////////////////////////////
End;

мм... Без ProcessMessages() почему-то не работает. Почему - хрен его знает...


TraderProg ©   (14.03.18 09:41[7]

Функция IsVariantNULL не известна для Delphi. Это системная VarIsNull или переименованная функция CheckVariant из соседней смежной ветки форума?:

Function CheckVariant(Variable: OleVariant): BooLean;
Begin
Result:=Not (VarIsNull(Variable) Or VarIsEmpty(Variable));
End;

В общем вставил я Ваш код в свой проект, определив IsVariantNULL как:
Function IsVariantNULL(Variable: OleVariant): BooLean;
Begin
Result:=(VarIsNull(Variable) Or VarIsEmpty(Variable));
End;

Вроде как заработало. Спасибо большое!

Redmond, немного не по теме еще вопрос. В инете нашел много способов понять загрузилась ли страница полностью в WebBrowser или нет. Но ни один из них не дожидается окончательной загрузки. С Хромиумом такой проблемы нет. Я пока просто поставил таймер и по прошествии минуты начинается работа с DOM. Но это "костыли" все-таки )))


Redmond   (14.03.18 16:45[8]

Да, всё верно сделали. Мне давно пора сделать модуль и куда-то выложить. Чтоб не писать по памяти, а то имена функций пишу как попало. :)

Нюанс в том, что даже если страница "официально полностью загрузилась" - это далеко не всегда обозначает что "пора делать свои дела".
Например JS может ещё что-то не доделать. А к тому же в JS есть своё подобие таймера. Иногда "ждать" как ни странно оказывается самым простым и действенным способом.
Главное не использовать Sleep с параметром больше нуля - оно не "ждёт", оно тупо замораживает поток.


Redmond   (14.03.18 17:00[9]

Хотя не до конца верно выразился - если в программе много потоков, то в "не главном потоке" использовать Sleep можно. Это в однопоточных пауках не пройдёт.

А вот "минуту" это вы чёт многоватто. Ждём события WebBrowser "завершено" и с этого момента может ещё пол-секунды или может полторы секунды.


TraderProg ©   (14.03.18 18:02[10]

Минуту поставил чтоб наверняка - VPS слабенький, бывает за пару секунд страница грузится, а бывает и секунд 30 )))


TraderProg ©   (15.03.18 07:50[11]

А по идее же наверно можно проверку длины List и существования Node заменить одним блоком Try...Except...End. То есть если ошибок не возникло то выполняется один код, а если на каком то из этапов возникла - то другой. Вроде как и код проще получается. Или будут какие то недостатки этого метода?


Redmond   (15.03.18 15:30[12]

И заодно не знать что и где произошло..?


TraderProg ©   (15.03.18 15:38[13]

Можно в блоке Except чтобы запись в журнал в Memo делать, хотя конечно будет грубо и непонятно где в List или в Node ошибка. Но это все-таки редкость и при следующем проходе снова определится и вероятно удачно.


версия для печати

Написать ответ

Ваше имя (регистрация  E-mail 







Разрешается использование тегов форматирования текста:
<b>жирный</b> <i>наклонный</i> <u>подчеркнутый</u>,
а для выделения текста программ, используйте <code> ... </code>
и не забывайте закрывать теги! </b></i></u></code> :)


Наверх

  Рейтинг@Mail.ru     Титульная страница Поиск, карта сайта Написать письмо