Конференция "Сети" » Работа с Web-платформой Olymp Trade
 
  • TraderProg © (11.02.18 09:02) [0]
    Здравствуйте! Собираюсь сделать торгового робота в Delphi для бинарных опционов, работающий в Web-плаформе Olymp Trade.
    Адрес платформы: https://olymptrade.com/ru-ru/platform
    Для доступа к платформе потребуется простенькая регистрация (это вручную).
    Для начала надо организовать:

    1. Чтение цены выбранного инструмента - на сайте имеется графический, динамический меняющийся уровень с цифрами в правой части экрана.
    2. Нажатие на кнопки "Выше" или "Ниже"

    Конечно потом возможно понадобится и чтение текущего баланса, регулировка стоимости и экспирации опциона, но пока самое главное эти 2 пункта.
    Перечитал много ресурсов про использование компонентов TWebBrowser и связки TIdHTTP + TIdSSLIOHandlerSocketOpenSSL

    Пробовал так:
    1. Для парсинга цены пробовал так:
    Memo1.Lines.Add(UTF8Decode(IdHTTP1.Get('https://olymptrade.com/ru-ru/platform')));

    Но вылазит ошибка "HTTP/1.1 403 Forbidden". При этом другие HTTPS сайты подгружаются нормально.
    Может конечно над считывать совершенно иначе.
    Код страницы, где видна динамически-меняющаяся цена, показан на скриншоте.

    2. Для работы с кнопками "Выше" и "Ниже" пытался так:
    Загрузка страницы в WebBrowser по команде
    WebBrowser1.Navigate('https://olymptrade.com/ru-ru/platform', Flags, TargetFrameName, PostData, Headers);
    или
    WebBrowser1.Navigate('https://olymptrade.com/ru-ru/platform');
    Здесь пока все нормально. А вот дальше уже проблемы.
    Далее непосредстенно клик на кнопке:
    WebBrowser1.OleObject.Document.GetElementById('svg_btn-up').click;
    Тут вылазит ошибка показанная на третьем скриншоте.
    Код страницы, где видны кнопки показан на втором скриншоте.

    Прошу помощи по крайней мере с этими самыми главными двумя пунктами. Сильно не пинайте, я начинающий программист-любитель.
    Возможно сайт с платформой написан нестандартно, так как не хотят работать классические примеры работы с сайтами в Delphi.
    Рассмотрю любые варианты организации работы с этой платформой, единственное мне не подходят варианты:
    1. Брать цену из других источников, так как она может отличаться
    2. Искать другой сайт, на котором заработают приведенные выше классические способы - тоже НЕТ, так как торговые условия устраивают меня лично только здесь.
  • TraderProg © (11.02.18 09:03) [1]
    Извините, но похоже скриншоты добавить не могу. Попробую перепечатать коды web-платформы в интересующих местах
  • TraderProg © (11.02.18 09:05) [2]
    Код где отображается текущая цена:

    <g class="cutoffG" transform="translate(0, 405)" style="visibility: visible;"><line class="cutoffLine" x1="0" x2="802" y1="0" y2="0" style="stroke: rgb(131, 140, 152); stroke-opacity: 0.7; shape-rendering: auto;"></line><path class="pin" d="M0,15L6.947213595499958,28.894427190999917A2,2,0,0,0,8.73606797749979,30L77.9 296875,30A2,2,0,0,0,79.9296875,28L79.9296875,2A2,2,0,0,0,77.9296875,0L8.73606797 749979,0A2,2,0,0,0,6.947213595499958,1.105572809000084" transform="translate(787.0703125,-15)" style="fill: rgb(50, 53, 81);"></path><text class="pin_text" text-anchor="end" y="2" dx="0" dy="3" x="862" style="font-size: 14px; font-family: "Open Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", Helvetica, "Liberation Sans", Arial, sans-serif; font-weight: bold; fill: rgb(255, 255, 255);">8058.657</text></g>
  • TraderProg © (11.02.18 09:06) [3]
    Текущая цена в приведенном выше тексте: 8058.657
  • TraderProg © (11.02.18 09:08) [4]
    Код где идет работа с кнопками "Выше" и "Ниже":

    <div class="state-block js_tu_deal_buttons deal-form__item deal-form__risk-free"><div class="buttons js_tu_deal_buttons"><div class="buttons-wrapper"><div class="container -up"><button data-test="deal-button-up"><svg class="svg"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#svg_btn-up"></use></svg><span class="spinner"> </span><span class="text" data-trans="deals_upper">Выше</span></button></div><div class="container -down"><button data-test="deal-button-down"><svg class="svg"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#svg_btn-down"></use></svg><span class="spinner"> </span><span class="text" data-trans="deals_lower">Ниже</span></button></div></div></div></div>
  • TraderProg © (11.02.18 09:10) [5]
    Вот как-то надо организовать взаимодействие и работу с этой Web-платформой из под Delphi. В крайнем случае на C# или VB
  • Redmond (13.02.18 00:35) [6]
    Одно из четырёх:
    * Вы используете API сайта (рекомендуется, если оно есть)
    * Вы изучаете какие запросы делает страница и пытаетесь повторить их (муторно и далеко не всегда этим вариантом можно сделать требуемое)
    * Вы скачиваете страницу и ковыряете текст (муторно и многие вещи будут недоступны, например скрипты и подкачка информации)
    * Вы загружаете страницу в TWebBrowser и тыкаете в DOM (оптимальный вариант, если ни API ни запросы вам не доступны)
  • Redmond (13.02.18 00:43) [7]
    Открываете страницу в Chrome, правой мышкой на нужный элемент и в выпадающем списке "Посмотреть код".
    В инструментах разработчика правой мышью на исследуемом/выделенном/нужном элементе и в выпадающем списке "Copy > Copy selector".
    После этого в буфере обмена у вас информация подсказывающая как этот элемент найти по DOM.
  • Дмитрий Белькевич © (13.02.18 10:29) [8]
    Если API нет, то грузи страницу в TWebBrowser. Если в тексте страницы есть нужные данные, можешь из TWebBrowser забрать этот же текст и попробовать его разобрать (распарсить).
    Можешь погуглить по запросу 'twebbrowser get html'

    Вот хотя бы:

    https://stackoverflow.com/questions/10091666/how-can-i-get-html-source-code-from-twebbrowser
  • TraderProg © (13.02.18 16:36) [9]
    Спасибо за ответы Redmond и Дмитрий Белькевич!
    1. API сайта не нашел
    2. Пытался через сниффер отследить запросы, но так и не понял ничего. Я новичок в этом деле.
    3. Код страницы в браузере я уже видел через кнопку F12 и нашел нужные участки с кодом. Только вот применить их в самом Delphi пока не пойму как.
    4. В TWebBrowser и так уже гружу. А по DOM можно поподробнее?

    По ответу Дмитрия Белькевича: попробую извлечь HTML из TWebBrowser без применения TIdHTTP, о результатах напишу.  Только вот это пол дела - для чтения текущей цены сгодится, но как мне по кнопкам на Веб-странице нажать? Как уже писал по id нашел кнопку, кликаю как в распростарненных примерах, но ошибка вылазит. Возможно не пот тому элементу кликаю. По кликам на других элементах вылазит даже более грубая ошибка.
  • TraderProg © (13.02.18 18:21) [10]
    Проблему №1 по парсингу цены частично решил. Удалось вывести код страницы в Memo аж двумя разными способами:
    1-й:
    function GetWebBrowserHTML(const WebBrowser: TWebBrowser): String;
    var
     LStream: TStringStream;
     Stream : IStream;
     LPersistStreamInit : IPersistStreamInit;
    begin
     if not Assigned(WebBrowser.Document) then exit;
     LStream := TStringStream.Create('');
     try
       LPersistStreamInit := WebBrowser.Document as IPersistStreamInit;
       Stream := TStreamAdapter.Create(LStream,soReference);
       LPersistStreamInit.Save(Stream,true);
       result := LStream.DataString;
     finally
       LStream.Free();
     end;
    end;

    2-й:
    function GetHTML(w: TWebBrowser): String;
    Var
     e: IHTMLElement;
    begin
     Result := '';
     if Assigned(w.Document) then
     begin
        e := (w.Document as IHTMLDocument2).body;

        while e.parentElement <> nil do
        begin
          e := e.parentElement;
        end;

        Result := e.outerHTML;
     end;
    end;

    Первый способ работает довольно шустро, но выдает всего 12 кб текста, а второй - несколько секунд думает (даже на моем мощном игровом компе) и выдает 500 кб текста. Первый способ не подходит так как поиск текста не находит нужные элементы в коде. А второй слишком медленный - цена меняется по несколько раз за секунду, а вывод кода в Memo - несколько секунд !!!

    В связи с этим вопрос - возможно ли как-то быстро считывать цену из этого куска текста в 500 кб - чтобы поспевать за ценой?
  • TraderProg © (13.02.18 18:54) [11]
    Может как-то можно из TWebBrowser выгружать нужный участок кода, для экономии времени?
  • TraderProg © (13.02.18 18:59) [12]
    По второй проблеме (как программно нажать на кнопку) по совету Redmond я через Copy selector получил в буфере обмена следующий текст:

    #deal_controls > div > div.deal-form > div.state-block.js_tu_deal_buttons.deal-form__item.deal-form__risk-free > div > div > div.container.-down > button > span.text

    Что с этим делать? Как этот "DOM" работает?
  • Redmond (13.02.18 20:54) [13]
    TIdHTTP - это скачивание страницы, оригинального HTML-кода, без дополнительных ресурсов, без отрабатывания JavaScript/событий/AJAX'ов. При таком вот простом скачивании довольно часто нужной информации там может просто физически не быть (зависит от сайта).
    Кстати если надо только лишь скачивать файл по ссылке - можно не тянуть весь Indy, а воспользоваться функцией URLDownloadToFile() из модуля Winapi.UrlMon.

    TWebBrowser - загружает страницу, загружает ресурсы, генерирует события, выполняет JavaScript'ы. Он хорош тем что скорее всего нужная информация там должна быть и не надо ковырять запросы (которые легко могут однажды взять и измениться полностью).

    Первый момент  - не уверен, но вроде бы из TWebBrowser можно доставать не только "текущий DOM", но и "начальный DOM" (то есть фактически то что получаем через TIdHTTP/URLDownloadToFile) - возможно ваш "первый способ" получает как раз "начальный".
    Второй момент - надо бы на всякий случай поправить FEATURE_BROWSER_EMULATION, Гугл знает что это.
    Третье - почему outerHTML, а не inner, да ещё и от body? Не проще найти элемент поближе к целевому узлу?

    Версия Delphi? Версия IE? Если у версии DOM доступен метод querySelectorAll() удобнее будет через него. Вы планируете каждый раз делать Navigate(), или оно там и так само обновляется?
  • Redmond (13.02.18 21:21) [14]
    Наколеночная мини-демонстрация:
    Procedure TForm1.Button1Click(Sender: TObject);
    Var i: Integer; Doc, List, Node: OleVariant;
    Begin
    With TButton(Sender) Do
         Begin
         Enabled:=False;
         Caption:='Loading...';
         WB.Navigate(URL);
         While (WB.ReadyState<>READYSTATE_COMPLETE) Do
               Application.ProcessMessages();
         Caption:='Working...';
         Doc:=WB.Document;
         List:=Doc.querySelectorAll('button');
         For i:=0 To (List.length-1) Do
               Begin
               Node:=List.item(i);
               Node.style.border:='solid red 8px';
               End;
         ShowMessage(Format('Найдено и обведено элементов:   %d', [Integer(List.length)]));
         Caption:='Done!';
         Enabled:=True;
         End;
    End;
  • TraderProg © (13.02.18 21:28) [15]
    1. Поизучаю, что такое "DOM"
    2. Проверю у себя, позже напишу.
    3. По поводу outerHTML и inner брал готовый пример, лишь смутно представляю что там происходит, так как новичок. Попробую поэкспериментировать, только не пойму как попасть поближе к целевому узлу для сокращения объема и соответственно повышения скорости.

    Версия Delphi - 10.2. Версия IE - 11.

    Нет, Navigate() выполняется единократно при загрузке веб-страницы в TWebBrowser, а далее он пашет сам - цена движется сама, можно мышкой покликать по кнопкам "Выше", "Ниже" например, то есть ведет себя как полноценный браузер (хотя я может вопрос неправильно понял). только как это сделать, чтобы не урками по кнопкам сайта клацать, а автоматом шло, то есть как заставить выполняться скрипт прописанный в коде веб-страницы из под Delphi.
  • ухты © (14.02.18 00:55) [16]

    >  В крайнем случае на C#
    тогда все проще, пишите маленькую сборочку, и все дела)
  • TraderProg © (14.02.18 18:47) [17]
    Ура, есть первые успехи! Получилось кликать по необходимым кнопкам. Спасибо, Redmond, за пример кода - именно он мне помог найти верное направление.
    Вот  рабочий код (сама страница цеж ранее загружена в WebBrowser):
    procedure TForm1.Button8Click(Sender: TObject);
    Var  Doc, List, Node: OleVariant;
    Begin
     Doc:=WebBrowser1.Document;
     List:=Doc.querySelectorAll('button');
     Node:=List.item(23);
     //23 - для кнопки "ВВЕРХ", 24 - "ВНИЗ"
     Node.click;
     //23 - вверх, 24 - вниз
    end;

    Коды 23 и 24 нашел методом перебора. Может конечно более "элегантно" как-то их находить без применения кодов 23 и 24 (на случай если веб-страницу изменят авторы), но уж ладно, главное что заработало

    Теперь осталось как-то быстро находить цену, отфильтровав лишнее без полной загрузки всего HTML-кода. Буду теперь думать какой теперь тип использовать, кнопки нашлись по типу "button"
  • TraderProg © (14.02.18 19:00) [18]
    Copy selector для текста с ценой выдает такую иерархию:

    #chart > div > svg > g > g.cutoffG > text
  • TraderProg © (14.02.18 19:25) [19]
    Итак, с ценой тоже вышло по индексу "6". Вот код:

    procedure TForm1.Button8Click(Sender: TObject);
    Var i: Integer; Doc, List, Node: OleVariant;
    Begin
     Doc:=WebBrowser1.Document;
     List:=Doc.querySelectorAll('text');
     Node:=List.item(6);
     Memo1.Lines.Clear;
     Memo1.Lines.Add(Node.innerHTML);
    end;

    Только одно маленькое "НО" осталось: в WebBrowser цена сама меняется - мне программно для этого даже делать ничего не надо. Но как оно происходит? Наверно генерируется какое-то событие и цена в нем обновляется? Если это так то какое это событие?
    Можно конечно повесить таймер и обновлять периодически цену. Но может можно обойтись без этого и обновлять цену в Memo1 лишь тогда, когда она изменяется в WebBrowser? Есть идеи как это сделать?
 
Конференция "Сети" » Работа с Web-платформой Olymp Trade
Есть новые Нет новых   [118411   +33][b:0][p:0.001]