Kiedy strona jest w pełni załadowana przez kompontent TChromium DCEF3?

0

Poszukiwałem różnych sposobów sprawdzania, kiedy strona jest w pełni załadowana przez składnik TChromium - na razie bezskutecznie.

Próbowałem użyć opóźnienia ładowania strony i przesłać informacje o zakończeniu przez dodatkową zmienną, ale zdarzenie OnLoadEnd jest wyzwalane przed JS i innymi podobnymi, więc nie zawsze uzyskać poprawne informacje.

procedure Chromium1.OnLoadEnd(Sender: TObject; const browser: ICefBrowser;
  const frame: ICefFrame; httpStatusCode: Integer);
var EndTime: TTime;
begin
  EndTime := IncSecond(Now, 2);
  repeat Application.ProcessMessages until (Now > EndTime);
  IsChromiumBusy := False;
end;

Czytałem, że mogę wykonać JS injection i dodać obiekt, który powinien pojawić się na końcu:

Chromium1.Load('https://www.wp.pl');
Form1.Chromium1.Browser.MainFrame.ExecuteJavaScript('$("body").prepend(''<input type="text" id="msoftval" value=""/>'')', '', 0);
Form1.Chromium1.Browser.MainFrame.ExecuteJavaScript('$("#msoftval").val($("body").html());', '', 0);
Form1.Chromium1.Browser.MainFrame.VisitDomProc(getResult);
while result = '' do Application.ProcessMessages;

Ale nie rozumiem użycia QuestDomProc (getResult) z procedurą wewnątrz (dlaczego procedura jest argumentem dla VisitDomProc?):

procedure getResult(const doc: ICefDomDocument);
var
  q: ICefDomNode;
begin
  q := doc.GetElementById('msoftval');
  if Assigned(q) then
    result := q.GetValue
  else
    result := '';
end;

Co należy zadeklarować jako rezultat i jak rezultat "wydobyć"? Czy ktoś mi to wytłumaczy?
Dzięki za porady.

0

Woziłem się z tym samym problemem. Ja rozwiązałem to tak:


type
  FOnGetEventValue= procedure(const pValue: string) of object;

procedure TfmWBForm.DocumentComplete(const doc: ICefDomDocument);
  procedure ProcessNode(ANode: ICefDomNode);
  var
    Node: ICefDomNode;
  begin
    if Assigned(ANode) then
    begin
      Node := ANode.FirstChild;
      while Assigned(Node) do
      begin
        if Node.GetElementAttribute('class') = 'nazwaInteresującejMnieKlasy' then
        begin
            if Assigned(FOnGetEventValue) then
            begin
                FOnGetEventValue(Node.ElementInnerText);
                Exit;
            end;
        end;
        ProcessNode(Node);
        Node := Node.NextSibling;
      end;
    end;
  end;
begin
  ProcessNode(doc.Body);
end;
0

Jeśli dobrze rozumiem przebieg - będę dzięki temu w stanie wyłapać konkretne, interesujące mnie klasy, np. świadczące o załadowaniu całej strony. Kiedy natomiast nie jestem w stanie przewidzieć która konkretnie klasa kończy stronę, rozumiem też, że będę musiał wstrzelić do treści strony jakąś klasę? Przepraszam jeśli pytanie wyda się infantylne, ale w jakiej kolejności będą wykonywane te klasy? Ta którą wstrzelę zgodnie z moim pierwszym komentarzem będzie pierwsza czy ostatnia?

Bardzo dziękuję za info!

P.S. I do czego następuje w Twojej procedurze zapisanie informacji o procesie zakończonym powodzeniem?

0

problem w tym, że ładowanie dokumentu HTML przez request HTTP nie jest tożsame z kompletnym załadowaniem strony, wiele dzisiejszych serwisów używa AJAXA i timeouta do doczytywania zawartości stron, dlatego bez dokładnej inspekcji zawartości oczekiwanej przez nas klasy nie jest możliwe wykrycie tego zdarzenia.

0

W zasadzie to rozwiązaniem problemu jest odczekanie określonego czasu i dopiero pobieranie zawartości, ale to chyba nie jest większy problem jeśli nie potrzebna jest duża wydajność obliczeniowa?

A tymczasem - wciąż mam wątpliwości, bo nie wiem jak rozumieć zaproponowany przez kolegę kod.

1 użytkowników online, w tym zalogowanych: 0, gości: 1