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

Откуда:
Сообщений: 401
X11,
Сформулируй задачу!
28 авг 19, 16:01    [21959207]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 13227
Парсинг сайта в отдельном потоке с использованием Cef4Delphi без дополнительного окна.
По ходу действа искать не только нужный текст, который можно сохранить в базу, но и нужный текст ссылок, по которым нужно кликать, например, чтобы открыть объявление, контакты или вернуться назад и перейти не следующую страницу.
28 авг 19, 16:11    [21959222]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
ziv-2014
Member

Откуда:
Сообщений: 401
X11
Парсинг сайта в отдельном потоке с использованием Cef4Delphi без дополнительного окна.
По ходу действа искать не только нужный текст, который можно сохранить в базу, но и нужный текст ссылок, по которым нужно кликать, например, чтобы открыть объявление, контакты или вернуться назад и перейти не следующую страницу.

Зачем парсить сайт в отдельном потоке? Chromium создает несколько процессов для парсинга, тебе этого мало?
Может сделать со скрытым окном?
28 авг 19, 16:21    [21959234]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 13227
ziv-2014
Может сделать со скрытым окном?


сейчас это вопрос изучаю
21959107
28 авг 19, 16:27    [21959245]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 13227
ziv-2014
Зачем парсить сайт в отдельном потоке? Chromium создает несколько процессов для парсинга, тебе этого мало?


потому что не хочется создавать новый проект и новую программу, в которой уже есть несколько других работающих парсеров, так сказать оболочка есть и к ней нужно прикрутить ещё один с браузером и чтобы не машать работе пользователя.
28 авг 19, 16:29    [21959248]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
ziv-2014
Member

Откуда:
Сообщений: 401
X11, Разве примера из DOMVisitor не достаточно?
28 авг 19, 16:35    [21959254]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
X11
Member

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

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

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


Заходим на страницу объявления и выполняем скрипт.


получилось без окон и панелей загрузить страницу в фоне и выполнить JS

  constJS =  '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(); ' +
             '         console.log("my click"); ' +
             '      } ' +
             '    } ' +
             '  }' +
             '}';


В итоге в консоль в DevTools попало сообщение "my click"
28 авг 19, 16:36    [21959256]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
ziv-2014
Member

Откуда:
Сообщений: 401
X11
ziv-2014
Зачем парсить сайт в отдельном потоке? Chromium создает несколько процессов для парсинга, тебе этого мало?


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

Вы не понимаете, как работает chromium. Там есть очередь обработки сообщений. Все операции выполняются в отдельных потоках. Результат выводится в главный поток для отображения. Все операции, которые происходят внутри, chromium уже распределяет по нужным ему потокам. Если вам надо сделать в отдельном потоке, то вам надо делать окно в отдельном потоке и обрабатывать сообщения этого окна. Но по-моему это большие грабельки.
28 авг 19, 16:40    [21959262]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 13227
ziv-2014
X11, Разве примера из DOMVisitor не достаточно?


Изучаю три примера.

На данный момент волнует вопрос, можно ли управлять общаться с браузером не из главного потока программы, а из дополнительного.
Пока не пробовал. Пока изучаю ...
28 авг 19, 16:42    [21959265]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 13227
ziv-2014
Вы не понимаете, как работает chromium.


не спорю, поэтому и пытаюсь изучать и понять. К сожалению инфы на русском мало.
28 авг 19, 16:42    [21959266]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 13227
Подскажите, а что нужно указывать в качестве NodeID?


procedure SimpleNodeSearch(const aDocument: ICefDomDocument; const frame: ICefFrame; const NodeID: string);
var
  TempNode: ICefDomNode;
  msg: ICefProcessMessage;
begin
  try
    if aDocument <> nil then
    begin
      TempNode := aDocument.GetElementById(NodeID);
      msg := TCefProcessMessageRef.New(msg_for_chromium);

      if TempNode <> nil then
      begin
        msg.ArgumentList.SetString(0, 'Node found: ' + NodeID);
        msg.ArgumentList.SetString(1, 'Node name: ' + TempNode.Name);
        msg.ArgumentList.SetString(2, 'ElementInnerText: ' + TempNode.ElementInnerText);
        msg.ArgumentList.SetString(3, 'ElementTagName: ' + TempNode.ElementTagName);

      end
      else
        msg.ArgumentList.SetString(0, 'ERROR. Node not found: ' + NodeID);

      frame.SendProcessMessage(PID_BROWSER, msg);
    end;
  except
    on e : exception do
      if CustomExceptionHandler('SimpleNodeSearch', e) then raise;
  end;
end;


передаю "ad-author-contact-row-content" или "ad-author-contact-row-content j-c-phones" и процедура его не находит.

К сообщению приложен файл. Размер - 13Kb
29 авг 19, 13:52    [21959833]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
asviridenkov
Member

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

Это классы а не id
29 авг 19, 13:58    [21959839]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 13227
Ну т.е. с помощью GetElementById не получится?
29 авг 19, 14:04    [21959847]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
asviridenkov
Member

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

нет
29 авг 19, 14:29    [21959870]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 13227
ок, тогда с помощью чего найти телефон или признак телефона во время итерации по DOM?

procedure SimpleDOMIteration(const aDocument: ICefDomDocument; const frame: ICefFrame);
var
  TempHead, TempChild : ICefDomNode;
  msg: ICefProcessMessage;
begin
  try
    if aDocument <> nil then
    begin
        TempHead := aDocument.Body;

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

          while TempChild <> nil do
          begin
            Msg := TCefProcessMessageRef.New(msg_for_chromium);
            if TempChild.ElementInnerText = '' then
            begin
              TempChild := TempChild.NextSibling;
              Continue;
            end;

            msg.ArgumentList.SetString(0, 'name: ' + Trim(TempChild.Name));
            msg.ArgumentList.SetString(1, 'TagName: ' + Trim(TempChild.ElementTagName));
            msg.ArgumentList.SetString(2, 'InnerText: ' + 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;
29 авг 19, 15:07    [21959915]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
asviridenkov
Member

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

Ну например использовать префикс tel в href
29 авг 19, 15:09    [21959916]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 13227
asviridenkov
использовать префикс tel в href


не понял
29 авг 19, 15:13    [21959921]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 13227
Если на примере цикла итерации по DOM, то как?

procedure SimpleDOMIteration(const aDocument: ICefDomDocument; const frame: ICefFrame);
var
  TempHead, TempChild : ICefDomNode;
  msg: ICefProcessMessage;
  attrList: TStrings;
begin
  try
    if aDocument <> nil then
    begin
        TempHead := aDocument.Body;

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

          while TempChild <> nil do
          begin
            Msg := TCefProcessMessageRef.New(msg_for_chromium);
            if TempChild.ElementInnerText = '' then
            begin
              TempChild := TempChild.NextSibling;
              Continue;
            end;

            msg.ArgumentList.SetString(0, 'name: ' + Trim(TempChild.Name));
            msg.ArgumentList.SetString(1, 'TagName: ' + Trim(TempChild.ElementTagName));

            attrList := TStringList.Create;
            try
              TempChild.GetElementAttributes(attrList);

              msg.ArgumentList.SetString(2, 'attrList: ' + attrList.Text);
            finally
              attrList.DisposeOf;
            end;

            msg.ArgumentList.SetString(3, 'InnerText: ' + Trim(TempChild.ElementInnerText));
            msg.ArgumentList.SetString(4, '**********************');


            frame.SendProcessMessage(PID_BROWSER, msg);

            TempChild := TempChild.NextSibling;
          end;
        end;
    end;
  except
    on e : exception do
      if CustomExceptionHandler('SimpleDOMIteration', e) then raise;
  end;
end;
29 авг 19, 15:19    [21959930]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 13227
Я ещё не могу понять/найти: в каком свойстве, где живёт то, что на картинке подчеркнуто в программе в ICefDomNode?

Т.е. как выловить, в каком свойстве вот то название класса "ad-author-contact-row-content j-c-phones", чтобы как можно ближе подобраться к телефону.

Т.е. когда я в Firefox выбираю "копировать/внутренний HTML", то копируется:
<span><a href="tel:+xxxxxxx0">+xxxxxxx0</a></span>


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

Откуда: Kharkiv, Ukraine
Сообщений: 13227
я забыл про рекурсию
29 авг 19, 15:59    [21959966]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 13227
X11
.е. как выловить, в каком свойстве вот то название класса "ad-author-contact-row-content j-c-phones", чтобы как можно ближе подобраться к телефону.

Т.е. когда я в Firefox выбираю "копировать/внутренний HTML", то копируется:


в общем, там ещё есть "TempChild.AsMarkup", т.е. можно использолвать вместо "TempChild.ElementInnerText"
30 авг 19, 12:04    [21960433]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 13227
X11
procedure SimpleDOMIteration(


извините за такой вопрос, но сегодня пятница, так что можно Картинка с другого сайта.

Я не могу понять, обходит ли SimpleDOMIteration() ВСЕ узлы и все уровни дерева DOM или только узлы верхнего уровня? Процедура не является рекурсивной, но вижу заход (TempChild := TempHead.FirstChild) на дочерние узлы.
30 авг 19, 13:20    [21960514]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 13227
В общем, вот такая конструкция у меня получилась, может кому пригодится.

+ найти нужный атрибут и значение узла в цикле по DOM
procedure StartDOMIteration(const aDocument: ICefDomDocument; const frame: ICefFrame);
var
  TempNode, TempChild : ICefDomNode;
  attrList: TStrings;
  InnerHTMLText, val: string;
begin

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

        if TempNode <> nil then
        begin

          TempChild := TempNode.FirstChild;

          while TempChild <> nil do
          begin
            RecourceDOMIteration(frame, TempChild);

            if SearchNodeAttr(frame, 'class=j-c-phones', TempChild) then
            begin
              SendMessageToBrowser(frame, msg_for_chromium, Trim(TempChild.ElementInnerText));
              exit;
            end;

            TempChild := TempChild.NextSibling;
          end;
        end;

    end;
  except
    on e : exception do
      if CustomExceptionHandler('StartDOMIteration', e) then raise;
  end;
end;

procedure RecourceDOMIteration(const frame: ICefFrame; CefDomNode: ICefDomNode);
var
  TempChild : ICefDomNode;
  attrList: TStrings;
  InnerHTMLText, val: string;
begin
  try
    if CefDomNode <> nil then
    begin
      TempChild := CefDomNode.FirstChild;

      while TempChild <> nil do
      begin
        RecourceDOMIteration(frame, TempChild);

        if SearchNodeAttr(frame, 'class=j-c-phones', TempChild) then
        begin
          SendMessageToBrowser(frame, msg_for_chromium, Trim(TempChild.ElementInnerText));
          exit;
        end;


        TempChild := TempChild.NextSibling;
      end;
    end;

  except
    on e : exception do
      if CustomExceptionHandler('RecourceDOMIteration', e) then raise;
  end;
end;

procedure SendMessageToBrowser(const frame: ICefFrame; const sMsg, sText: string);
var
  msg: ICefProcessMessage;
begin
  Msg := TCefProcessMessageRef.New(sMsg);
  msg.ArgumentList.SetString(0, sText);
  frame.SendProcessMessage(PID_BROWSER, msg);
end;

function SearchNodeAttr(const frame: ICefFrame; const aSearchAttrText: string; const Node: ICefDomNode): boolean;
var
  attrList: TStrings;
  InnerHTMLText, val: string;
begin
  Result := false;

  attrList := TStringList.Create;
  try

    Node.GetElementAttributes(attrList);

    if Trim(attrList.CommaText) = aSearchAttrText then
      Result := True;

  finally
    attrList.DisposeOf;
  end;
end;
30 авг 19, 15:48    [21960672]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
JaDi
Member

Откуда: Сызрань, Россия
Сообщений: 4028
Это же жесть -- вручную перебирать всю структуру DOM. Есть всякие css-селекторы, которые простыми командами могут найти и вывести любое количество элементов. Судя по вот этому -- CEF полностью поддерживает querySelectorAll.
31 авг 19, 22:43    [21961333]     Ответить | Цитировать Сообщить модератору
 Re: CEF4Delphi в потоке с внешней формой  [new]
X11
Member

Откуда: Kharkiv, Ukraine
Сообщений: 13227
Это просто один из способов. Тем более, не надо изучать JS.
1 сен 19, 09:50    [21961400]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: Ctrl  назад   1 2 [3] 4   вперед  Ctrl      все
Все форумы / Delphi Ответить