Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
Топик располагается на нескольких страницах: Ctrl  назад   1 [2] 3 4   вперед  Ctrl      все
 Re: CEF4Delphi в потоке с внешней формой  [new]
Saller
Member

Откуда: exUSSR
Сообщений: 1135
X11
doska.plus

var links = document.querySelectorAll('a.link-ajax.j-v-contacts-expand-link');
if (links) {
    for (var x = 0; x <= links.length; x++) {
        if (links[x]) {
            if (links[x].innerHTML.trim().indexOf('показать контакты') != -1) {
                links[x].click();               
            }
        }
    }
}
21 авг 19, 09:38    [21954002]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 13226
Так это ж недельфи код
21 авг 19, 09:44    [21954004]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
Saller
Member

Откуда: exUSSR
Сообщений: 1135
X11
Так это ж недельфи код
Тебе ведь нужно кликнуть на странице по ссылке? Скриптом это сделать проще всего (скармливай скрипт CEF4D). Собрать нужную информацию тоже можно скриптом, но на Делфи это тоже без особых проблем можно сделать. В чем сложность? Может я не правильно понял твою задачу.
21 авг 19, 09:59    [21954013]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 13226
я не понимаю, что такое скармливай. как, куда?
где, в какой момент?

Я cef4 только начал изучать
21 авг 19, 10:29    [21954051]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 13226
Saller
Может я не правильно понял твою задачу.


Задача простая: спарсить параметры объявления + контакты в свою базу
21 авг 19, 10:30    [21954053]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
энди
Member

Откуда: Киров, Россия
Сообщений: 999
Это бессмысленная задача причем даже в ближайшей перспективе :)
Сейчас телефон в текстовом виде, а когда запалитесь он станет в виде картинки, начнете распознавать картинку и он станет с вотермарками и прочими прелестями.
21 авг 19, 11:50    [21954181]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
Saller
Member

Откуда: exUSSR
Сообщений: 1135
X11
я не понимаю, что такое скармливай. как, куда?
где, в какой момент?

Я cef4 только начал изучать

Возьми любую демку CEF4Delphi (например MiniBrowser), добавь туда Memo поле для ввода скрипта и кнопку для выполнения скрипта. В Обработчике клика кнопки прописывает
Chromium1.Browser.MainFrame.ExecuteJavaScript(Memo1.Text, Chromium1.Browser.MainFrame.Url, 0);

Заходим на страницу объявления и выполняем скрипт.
21 авг 19, 12:40    [21954271]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
Saller
Member

Откуда: exUSSR
Сообщений: 1135


К сообщению приложен файл. Размер - 99Kb
21 авг 19, 12:47    [21954287]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 13226
Отлично. Спасибо.

А как узнать, что страница полностью загружена?
Использую OnLoadEnd, но оно срабатывает несколько раз, видать на окончание загрузки каждого фрейма.
но строка
if frame.IsMain then


всегда возвращает false
21 авг 19, 13:01    [21954316]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
Saller
Member

Откуда: exUSSR
Сообщений: 1135
X11
Отлично. Спасибо.

А как узнать, что страница полностью загружена?
Использую OnLoadEnd, но оно срабатывает несколько раз, видать на окончание загрузки каждого фрейма.
но строка
if frame.IsMain then



всегда возвращает false
Как вариант в событии OnLoadEnd перечитывать список фреймов и проверять все ли фреймы прогрузились. Но это конечно костыльный вариант, лучше спросить у разраба какие есть варианты определения полной загрузки страницы. Хотя может хватить и загрузки главного фрейма, чтобы начать выполнять свои операции.
21 авг 19, 14:05    [21954412]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
Saller
Member

Откуда: exUSSR
Сообщений: 1135
Или же в событии LoadingProgressChange дождаться 100% загрузки.
21 авг 19, 14:08    [21954417]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 13226
в onLoadError появляется ошибка

Chromium1.LoadEnd, frame url: about:blank
Error code:-3 - Error text :'ERR_ABORTED' - URL:https://www.facebook.com/tr/


и на этом, как я понял, дальнейшая загрузка прекращается...
а что сделать, чтобы ошибка игнорировалась и загрузка продолжалась?

Или где и как правильно вставить
Chromium1.Browser.MainFrame.ExecuteJavaScript(MemoJS.Text, Chromium1.Browser.MainFrame.Url, 0);
21 авг 19, 14:14    [21954426]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
Кроик Семён
Member

Откуда: СПб --> Dortmund
Сообщений: 6510
X11,

проскакивал тут как-то интересный топик с (мне тогда) неизвестным термином "HeadLess browser": Delphi + HeadLess браузер. Может поможет как-нибудь ...
21 авг 19, 14:14    [21954427]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
Василий 2
Member

Откуда:
Сообщений: 700
Безголовый браузер и код на ноде или яве - это наилучшее решение по безгеморройности и быстроте написания.
Но если это не вариант, то внедрение на страницу своего скрипта будет очень хорошим и гибким вариантом. Скрипт можно класть рядом с программой и менять без пересборки, а из js жонглировать DOM объектами куда проще, чем из интерфейса обертки.
21 авг 19, 18:52    [21954765]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 13226
Подскажите, а у браузера есть возможность получить InnerHTML?
Я почитал: https://www.briskbard.com/forum/viewtopic.php?t=157#p567
дык там нужно такой... огород городить приходится О_о

Ну т.е. нет ли чего-нибудь типа Chromium1.Browser.MainFrame.InnerHTML?
24 авг 19, 16:16    [21956982]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
sql2012
Member

Откуда: РФ
Сообщений: 687
X11,

в LoadEnd
if (frame <> nil) and frame.IsMain then
    begin
      frame.GetSourceProc(crmLoadEndcallback);
    end;



procedure crmLoadEndcallback(const str: ustring);
begin
 str = исходный текст ...
end;
24 авг 19, 20:44    [21957044]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
sql2012
Member

Откуда: РФ
Сообщений: 687
а ... InnerHTML ... напутал..)
24 авг 19, 20:45    [21957045]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 13226
Ещё вопрос по примеру DOMVisitor.

В процедуре GlobalCEFApp_OnProcessMessageReceived есть возможность обратиться к фреймам. Хочу сделать цикл по фреймам, но FrameCount возвращает 0 и CefFrameIdentifierArray тоже нулевого размера.

var
  FrameCount: NativeUInt;
  CefFrameIdentifierArray: TCefFrameIdentifierArray;
begin
...
...
  browser.GetFrameIdentifiers(FrameCount, CefFrameIdentifierArray);
  
  CefLog('CEF4Delphi', 1, CEF_LOG_SEVERITY_INFO, 'browser.FrameCount: ' + FrameCount.ToString);
  CefLog('CEF4Delphi', 1, CEF_LOG_SEVERITY_INFO, 'CefFrameIdentifierArray: ' + Length(CefFrameIdentifierArray).ToString);

Что я делаю не так?
24 авг 19, 21:07    [21957050]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 13226
при этом
browser.FrameCount

возвращает 3
24 авг 19, 21:18    [21957053]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 13226
дошло, нужно
TempHead := aDocument.Body;
вместо
TempHead := aDocument.Head;
24 авг 19, 22:27    [21957074]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 13226
Итак... чтобы кликнуть на ссылку и потом получить текст страницы нужно примерно такие действия.
Делал на примере MiniBrowser.

В событии TChromium1 OnLoadEnd отправляем сообщение процесу рендеринга:
procedure TMiniBrowserFrm.Chromium1LoadEnd(Sender: TObject;
  const browser: ICefBrowser; const frame: ICefFrame;
  httpStatusCode: Integer);
var
  TempMsg: ICefProcessMessage;
begin

  if frame.IsMain then
  begin
    Memo1.Lines.Add('main frame load end: ' + TimeToStr(now));
    Chromium1.Browser.MainFrame.ExecuteJavaScript(MemoJS.Text, Chromium1.Browser.MainFrame.Url, 0);

    // Use the ArgumentList property if you need to pass some parameters.
    TempMsg := TCefProcessMessageRef.New(MSG3);// в MSG3 какой-то текст, в которому будем ловить сообщение в процедуре GlobalCEFApp_OnProcessMessageReceived()
    frame.SendProcessMessage(PID_RENDERER, TempMsg);// сообщение для процесса рендеринга
  end;
end;


В событии GlobalCEFApp.OnProcessMessageReceived ловим это сообщение:
procedure GlobalCEFApp_OnProcessMessageReceived(const browser       : ICefBrowser;
                                                const frame         : ICefFrame;
                                                      sourceProcess : TCefProcessId;
                                                const message       : ICefProcessMessage;
                                                var   aHandled      : boolean);
VAR
  TempVisitor : TCefFastDomVisitor2;
begin
  aHandled := False;
  CefLog('CEF4Delphi', 1, CEF_LOG_SEVERITY_INFO, 'GlobalCEFApp_OnProcessMessageReceived');
  if browser <> nil then
  begin
    CefLog('CEF4Delphi', 1, CEF_LOG_SEVERITY_INFO, 'message.name = ' + message.name);

    if message.name = MSG3 then
    begin
      TempVisitor := TCefFastDomVisitor2.Create(browser, Frame, DOMVisitor_OnDocAvailableSearch);
      frame.VisitDom(TempVisitor);
    end;
  end;

  aHandled := True;
end;



В процедуре DOMVisitor_OnDocAvailableSearch есть доступ к ICefDomDocument, именно он и нужен для итерации по DOM:
procedure DOMVisitor_OnDocAvailableSearch(const browser: ICefBrowser; const frame: ICefFrame; const document: ICefDomDocument);
begin
  CefLog('CEF4Delphi', 1, CEF_LOG_SEVERITY_INFO, 'DOMVisitor_OnDocAvailableSearch');
  SimpleDOMIteration(document, frame);// frame передаем для того, чтобы отправить сообщение обратно в TChromium
end;


Цикл по DOMу
procedure SimpleDOMIteration(const aDocument: ICefDomDocument; const frame: ICefFrame);
var
  TempHead, TempChild : ICefDomNode;
  msg: ICefProcessMessage;
begin
  CefLog('CEF4Delphi', 1, CEF_LOG_SEVERITY_INFO, 'SimpleDOMIteration');

  try
    if aDocument <> nil then
    begin
        TempHead := aDocument.Body;

        if TempHead <> nil then
        begin
          TempChild := TempHead.FirstChild;

          while TempChild <> nil do
          begin
            CefLog('CEF4Delphi', 1, CEF_LOG_SEVERITY_INFO, 'Head child element : ' + TempChild.Name + ', ElementInnerText: ' + Trim(TempChild.ElementInnerText));
// отправляем сообщение обратно в TChromium
            Msg := TCefProcessMessageRef.New(msg2);
            msg.ArgumentList.SetString(0, 'TempChild.ElementInnerText: ' + Trim(TempChild.ElementInnerText));
            frame.SendProcessMessage(PID_BROWSER, msg);

            TempChild := TempChild.NextSibling;
          end;
        end;
    end;
  except
    on e : exception do
      if CustomExceptionHandler('SimpleDOMIteration', e) then raise;
  end;
end;



отправляем в TMemo то, что прилетело из глобального процесса-рендеринга в message
procedure TMiniBrowserFrm.Chromium1ProcessMessageReceived(Sender: TObject;
  const browser: ICefBrowser; const frame: ICefFrame;
  sourceProcess: TCefProcessId; const message: ICefProcessMessage;
  out Result: Boolean);
begin
  Memo1.Lines.Add('Chromium1ProcessMessageReceived-1');

  Result := False;
  if (message = nil) or (message.ArgumentList = nil) then exit;

  Memo1.Lines.Add(message.Name);

  if message.Name = MSG2 then
  begin
    Memo1.Lines.Add(MSG2);
    Memo1.Lines.Add(message.ArgumentList.GetString(0));// данные здесь
  end;

  Result := True;
end;
26 авг 19, 17:34    [21957795]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 13226
VisitDom работает только в процессе, который занимается рендерингом
frame.VisitDom(TempVisitor);


Поэтому DOMVisitor_OnDocAvailableSearch и SimpleDOMIteration бесполезно вызывать из своего приложения.
26 авг 19, 18:06    [21957824]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 13226
Я пока так и не понял, что такое TCefFastDomVisitor2 и с чем его едят как и где правильно его использовать.
26 авг 19, 18:07    [21957826]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 13226
Посоветуйте, как лучше и правильней организовать парсинг в потоке с видимым окном.
Как из потока обращаться к окну, где будет работать компоненты TChromium + TCEFWindowParent? Нужно же обмениваться данными и не просто в 10-20 символов.
Просто Syncronize не подойдет, должна же быть какая-то взаимосвязь, отдача, очередь, синхронность?

Хоть с чего начать?
28 авг 19, 11:22    [21958892]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
Zelius
Member

Откуда: Россия, Москва
Сообщений: 1364
X11,

а что не так с Synchronize? Если туда передать объект, то можно и данными обмениваться.

Можно через SendMessage передать указатель на объект.
28 авг 19, 12:18    [21958969]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: Ctrl  назад   1 [2] 3 4   вперед  Ctrl      все
Все форумы / Delphi Ответить