Delphi-PRAXiS
Seite 2 von 2     12   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi auf EdgeBrowser.ExecuteScript warten (https://www.delphipraxis.net/215408-auf-edgebrowser-executescript-warten.html)

gubbe 28. Jun 2024 07:09

AW: auf EdgeBrowser.ExecuteScript warten
 
Ist "NavigationStarting" nicht viel zu früh?

Hier ist eine schöne Grafik, die den Ablauf zeigt:
https://learn.microsoft.com/de-de/mi...igation-events

An der Stelle ist ja noch gar nichts geladen und man kann die Navigation sogar noch verhindern. Es würde mich wundern, wenn man hier per Javascript schon Event-Handler setzen könnte. Theoretisch müsste das Script noch im Kontext der vorherigen Seiten ausgeführt werden. Wenn Du aber erfolgreich eine Rückmeldung kriegst, hast Du vielleicht Glück und die Scriptausführung wird verzögert bis zum Laden der Seite. Muss ich auch mal ausprobieren.

In der Grafik sieht man aber auch, dass NavigationCompleted nach DomContentloaded aufgerufen wird. Mein Beispiel mit DomContentloaded war hier also nicht sehr hilfreich, auch wenn es bei meinem Test funktionierte.

Also eigentlich wäre NavigationCompleted in Delphi das passende Ereignis, um den Quelltext auszulesen, da hier auch schon Bilder, Scripte etc. geladen sind. Wobei man nur für das Auslesen des Quelltextes evtl. gar nicht möchte, dass Bilder geladen werden, aber das ist ein anderes Thema. Man könnte auch direkt über einen HTTP-Aufruf den Quelltext lesen. Den Browser nutzt man, wenn man man einen Benutzer simulieren muss oder damit Javascript ausgeführt wird. Nur ist in NavigationCompleted zwar alles geladen, aber die Scripte starten teilweise auch erst dann, wenn sie z.B. auf "OnLoad" im Browser warten oder asynchron geladen werden.

Aber um die letzte Frage zu beantworten: Das JSON-Objekt brauchst Du hier ja nicht, weil nur ein String übermittelt wird. Es wäre aber möglich, auch JSON-Daten zu senden und in WebmassageReceived mit args.ArgsInterface.Get_webMessageAsJson auszulesen.

Die PN mit den Beispielwebseiten habe ich erhalten und schaue sie mir später an.

herik 28. Jun 2024 09:18

AW: auf EdgeBrowser.ExecuteScript warten
 
Du hattest natürlich recht, "NavigationStarting" ist zu früh. Das hatte auch nur bei den meisten Webseiten geklappt. Aber meiner "Problemwebseite" auch nicht.
OK, ich habe es jetzt nach deinem letzten Post nochmal umgestellt.

Jetzt sieht es so aus:

Delphi-Quellcode:
procedure TForm2.EdgeBrowser1NavigationCompleted(Sender: TCustomEdgeBrowser;
  IsSuccess: Boolean; WebErrorStatus: TOleEnum);
begin
  if IsSuccess then
  begin
    StatusBar1.Panels[0].Text := BoolToStr(IsSuccess);
    EdgeBrowser1.executescript('setTimeout(() => {chrome.webview.postMessage(document.documentElement.outerHTML);}, "2000");');
  end
  else
  begin
    Showmessage('Navigation nicht beendet');
  end;
end;


Delphi-Quellcode:
procedure TForm2.EdgeBrowser1ExecuteScript(Sender: TCustomEdgeBrowser;
  AResult: HRESULT; const AResultObjectAsJson: string);
var
  json: TJSONValue; //neu
begin
  json := TJSONObject.ParseJSONValue(AResultObjectAsJson);
  WebsiteContent_SL.Text:=json.AsType<string>;
  json.Free;
end;
Diese Procedure habe ich entfernt!


Delphi-Quellcode:
procedure TForm2.EdgeBrowser1WebMessageReceived(Sender: TCustomEdgeBrowser;
  Args: TWebMessageReceivedEventArgs);
var
  WebMessage: PWidechar;
begin
  args.ArgsInterface.TryGetWebMessageAsString(PWidechar(WebMessage));
  WebsiteContent_SL.Text:=WebMessage;
  DatenAbgreifen;
end;

Der aktuelle stand ist, das alles funktioniert.
Delphi-Quellcode:
EdgeBrowser1.executescript('setTimeout(() => {chrome.webview.postMessage(document.documentElement.outerHTML);}, "2000");');
die Zeile richtig eingesetzt und es hat gepasst.

gubbe 28. Jun 2024 09:48

AW: auf EdgeBrowser.ExecuteScript warten
 
Prima, dass es so klappt. Einfach 2 Sekunden zu warten ist natürlich nicht optimal, denn je nach Netzwerkverbindung kann es auch mal länger dauern, bis die Seite vollständig geladen ist. Oder es geht schneller und man verliert Zeit mit warten.

Deine Beispielseite habe ich mir angeschaut. Die verwendet tatsächlich ein Javascript-Framework (Angular) und lädt Daten dynamisch nach.

Der Vorgang startet auch erst im Event "DomContentloaded", daher ist das zu früh, um die Daten auszulesen. Eigentlich ist die Verwendung einer API ja ideal, weil man die Daten dann gleich dort abgreifen könnte, ohne sie umständlich aus dem Browser auszulesen. Das erfordert aber natürlich einen ganz anderen Ansatz. Sollte man eine Geschäftsbeziehung zu dem Anbieter haben, könnte man ja auch den offiziellen Weg gehen und nach einem API-Zugang fragen.

Aber nehmen wir mal an, das ist nicht möglich und möchte die Daten per Browser auslesen. Dann müsste man in NavigationCompleted ein Script ausführen, das wartet, bis die gesuchten Elemente erzeugt wurden und den HTML-Quelltext dann auslesen.

Hier ein Beispiel:
Delphi-Quellcode:
procedure TForm2.EdgeBrowser1NavigationCompleted(Sender: TCustomEdgeBrowser;
  IsSuccess: Boolean; WebErrorStatus: TOleEnum);
var
  Script: string;
begin
   Script := TFile.ReadAllText('script.js', TEncoding.UTF8);
   EdgeBrowser1.executescript(Script);
end;
Und die Datei script.js, die im Exe-Verzeichnis von Delphi liegen muss:
Code:
function waitForElements() {
    var elements = document.getElementsByClassName('productrow');
    if (elements.length > 0) {
      chrome.webview.postMessage(document.documentElement.outerHTML);      
    } else {
        setTimeout(waitForElements, 500);
    }
}

waitForElements();
Die Klasse "productrow" muss man natürlich anpassen an die Klasse der gesuchten Daten.
Natürlich ist noch der Fall zu berücksichtigen, dass keine Elemente erzeugt werden, weil eine Suche gar keine gefunden hat. Das muss eben individuell an die Seite angepasst werden.
Außerdem könnte man jetzt, nachdem man sowieso schon nach einzelnen HTML-Elementen sucht, diese auch gleich statt des gesamten Quelltextes an Delphi liefern und sich so die weitere Verarbeitung über Python sparen.

herik 28. Jun 2024 12:57

AW: auf EdgeBrowser.ExecuteScript warten
 
Nein, es ist nicht unbedingt optimal die 2 Sekunden zu warten. Aber bei mir spielt es jetzt keine Rolle. Wichtig ist nur das es funktioniert.

Und auch hier gebe ich dir recht. Die Verwendung einer API wäre natürlich der bessere Weg, aber für den überschaubaren Einsatz meiner Anwendung wäre das zu viel Aufwand (Absprachen Berechtigungen usw.)

Der Ansatz für die zusätzliche .JS klingt sehr interessant. Dies würde dann aber wirklich sehr speziell auf diese Webseite passen. Ich versuche aber mit dem Ansatz den ich jetzt habe erstmal alles zu erschlagen was da noch kommt.

Wie gesagt. Mein Projekt wird nur Zeitlich begrenzt benötigt, deswegen will ich auch nicht zu viel Energie hineinstecken.

Ich bin dir auf jeden Fall sehr dankbar für deine Hilfe und Geduld.:cheers:


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:59 Uhr.
Seite 2 von 2     12   

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz