IE Navigate und IEGetObjByID beschleunigen oder Alternative?

  • Hallo zusammen,


    ich habe danach gesucht aber leider nichts passendes gefunden.


    Ich möchte Werte auslesen, die mir Informationen über Warenbestände liefern.

    Allerdings muss ich ca 4.500 Abfragen in Summe senden, das dauert mit meiner jetzigen Methode ewig, ca 4-5 Stunden...


    Ich habe die Hoffnung dass mir jemand einen Tipp geben kann, wie ich das eventuell beschleunigen könnte.

    Den Link zur Website habe ich entfernt, da hier auch ein Userlogin nötig wäre...

    Habe bereits mit dem Anbieter selbst gesprochen, die Abfragen sind i.O. eine Bestandsdatei lässt er mir aber nicht zukommen, weil das so wohl nicht vorgesehen ist.


    Deshalb hoffe ich, dass jemand eine clevere Idee hat, die mir weiterhelfen könnte, hier meine zweckmäßige Lösung.


    Grüße und vielen Dank im Voraus,

    Leaves


  • Dennoch wäre ggf. interessant welche Webseite/Dienst das ist ggf. hat shcon jemand Erfahrung damit, um das mitzuteilen musst du ja keine Logindaten preis geben ;).


    Bei der Anzahl an Abfragen hört sich das nicht nach "normalen" Usereingaben an, sondern etwas was durchaus automatisiert über API oder direkt an die Server (ohne die Webseite dazwischen) laufen sollte. Dann solltest du auch um einiges schneller sein.

    Hat die Webseite eine API die du nutzen könntest oder direkte Serverabfragen?

  • Dennoch wäre ggf. interessant welche Webseite/Dienst das ist ggf. hat shcon jemand Erfahrung damit, um das mitzuteilen musst du ja keine Logindaten preis geben ;).


    Bei der Anzahl an Abfragen hört sich das nicht nach "normalen" Usereingaben an, sondern etwas was durchaus automatisiert über API oder direkt an die Server (ohne die Webseite dazwischen) laufen sollte. Dann solltest du auch um einiges schneller sein.

    Hat die Webseite eine API die du nutzen könntest oder direkte Serverabfragen?

    Handelt sich um WMKAT, - API gibts da leider nich, habe mit der IT gesprochen, - das Gesuch danach wurde abgelehnt, hätte natürlich auch lieber eine Liste aus dem FTP gefahren.

  • Handelt sich um WMKAT, - API gibts da leider nich, habe mit der IT gesprochen, - das Gesuch danach wurde abgelehnt, hätte natürlich auch lieber eine Liste aus dem FTP gefahren.

    ;) so viel zur Werbung "WM-KAT. Einfach. Effizient. Erleichtern und verbessern Sie jetzt die täglichen Arbeitsabläufe in Ihrer Werkstatt" :rofl:


    Die Webseite funktioniert auch nicht wirklich (wenn man versucht "mehr Informationen" zu bekommen XD)

    Kannst du das nicht ggf. über den angeblichen "Smart Client" abbilden? Ich bin mir sicher, das selbst wenn nicht, dieser auch nichts anderes macht als direkt mit den Servern und/oder API zu kommunizieren. Also Möglichkeiten gibt es, ob diese bereit gestellt werden von denen, ist wieder etwas anderes.

    Wenn sich da von deren Seite nichts rütteln lässt würde ich mir einen anderen Anbieter suchen...

  • Hey, - also mit dem Smart Client, da habe ich auch mal nachgesehen ob man da nicht nen sniffer zwischen hängen kann.

    Leider ist der Smart Client aber nix anderes als das WMKAT+, also einfach eine erweiterte Informationsquelle für Werkstätten, das brauch ich nicht.

    Auch der DataService, - der angeboten wird, - kann genutzt werden, der ist aber nur hilfreich um alle Artikel zu exportieren. Dadurch habe ich aber leider auch keine Verfügbarkeitsprüfung. Dadurch das ja auch noch die einzelnen Warenhäuser dargestellt werden statt nur das Zentrallager, ist das gar nicht so leicht mit den Abfragen.


    Eine Alternative würde ich natürlich nutzen, aber ich habe spezielle Bedarfe die aber teilweise aus Mindermengen bestehen, dafür kriege ich keine Kundenkonten bei HB Behru usw. große Bedarfe decke ich bereits woanders.


    Gäbe es denn eine Möglichkeit die Abfrage zu optimieren? Habe über mehrere Handler nachgedacht... oder einfach mehrere Instanzen... aber ich bin mir nicht sicher, wie ich das in "Serie" schalten soll.


    Grüße

  • Da muss ich leider passen, aber generell sieht die Schleife nicht so aus, als ob man sie noch verkürzen und damit Zeit sparen könnte.

    Dachte an einen großen anderen Anbieter (autoteile-markt.de evtl.?). Es wird sicherlich welche geben die eine API bereitstellen.

  • Um die Abfrage zu beschleunigen könntest Du die Datei compare.csv in einen Array einlesen und dann direkt auf die entsprechende Zelle zugreifen. Mit FileReadLine liest Du 4500 mal die Datei bis zur gewünschten Zeile durch.

    Das gilt auch für FileWriteLine. Wenn Du den Dateinamen angibst, dann wird die Datei jeweils geöffnet, der Datensatz geschrieben und die Datei wieder geschlossen.
    In einem Test mit 4500 Datensätzen dauert das 50848 ms gegenüber 4 ms.


    BTW: Wo wird $waitforload definiert?


    Setze mal einen Timer für _IENavigate. Vielleicht kann man daraus eine eigene Funktion erstellen und gewisse Fehlerprüfungen entfernen.

  • Um die Abfrage zu beschleunigen könntest Du die Datei compare.csv in einen Array einlesen und dann direkt auf die entsprechende Zelle zugreifen. Mit FileReadLine liest Du 4500 mal die Datei bis zur gewünschten Zeile durch.

    Das gilt auch für FileWriteLine. Wenn Du den Dateinamen angibst, dann wird die Datei jeweils geöffnet, der Datensatz geschrieben und die Datei wieder geschlossen.
    In einem Test mit 4500 Datensätzen dauert das 50848 ms gegenüber 4 ms.


    BTW: Wo wird $waitforload definiert?


    Setze mal einen Timer für _IENavigate. Vielleicht kann man daraus eine eigene Funktion erstellen und gewisse Fehlerprüfungen entfernen.

    Hi,


    danke für deine Antwort, darüber habe ich auch nachgedacht, da ich das woanders auch nutze. Also ReadtoArray, das werde ich gleich mal umstellen.

    Welche Alternative kann ich denn nutzen zum schreiben? Kann ich auch erst in einen anderen Array schreiben lassen? Wie greife ich den denn so ab, dass er in eine Datei schreibt?


    $waitforload wurde oben definiert ist aber einfach eine 1, die hatte ich entfernt, die Variable war noch ein Überbleibsel.


    - Zum Timer, wie genau meinst du das mit den Fehlerprüfungen und dem Timer? Sorry dazu habe ich jetzt keine Idee.


    Vielen Dank.


    Ich habs mal mit FileReadToArray gemacht, Geschwindigkeit hat es auf jeden Fall keine (spürbare) gebracht.

    Das was hier wohl noch immer am längsten dauert, ist wohl das Laden der Website, wobei die Array Variante natürlich die bessere ist.


    Viele Grüße,
    Leaves


  • So in etwa:

    • Die schreibenden Dateizugriffe habe ich auf Handle umgestellt
    • _IENavigate habe ich in zwei Befehle aufgespalten. _IENavigate und _IELoadWait. Beide werden für den ersten Durchlauf ausgewertet und das Ergebnis auf die Konsole ausgegeben.
    • Den Umbau von _FileCountLines überlasse ich Dir

    Je nach Laufzeit von _IENavigate und _IELoadWait sehen wir, wo wir den Sparstift ansetzen sollten.

  • So in etwa:

    • Die schreibenden Dateizugriffe habe ich auf Handle umgestellt
    • _IENavigate habe ich in zwei Befehle aufgespalten. _IENavigate und _IELoadWait. Beide werden für den ersten Durchlauf ausgewertet und das Ergebnis auf die Konsole ausgegeben.
    • Den Umbau von _FileCountLines überlasse ich Dir

    Je nach Laufzeit von _IENavigate und _IELoadWait sehen wir, wo wir den Sparstift ansetzen sollten.

    Hallo,


    anbei das Ergebnis und der Code

    Sichtbarer IExplorer

    _IENavigate dauerte 2.6993_IELoadWait dauerte 877.8491+>19:58:25 AutoIt3.exe ended.rc:0

    IExplorer im Hintergrund

    _IENavigate dauerte 2.478_IELoadWait dauerte 816.9387+>20:01:50 AutoIt3.exe ended.rc:0


    Quellcode

    Einfach mal in den Raum gefragt, indem man _IENavigate und _IELoadWait trennt... könnte man dann nicht einfach bspw.

    -> 10x IEXplore öffnen

    -> Jeweils Link 1 - 10 aufrufen

    -> Im Nachgang IELoadwait für alle IE Fenster anwenden

    -> In die Datei schreiben

    -> Die nächsten 10 Links etc....


    so verfahren? Sehe wohl blöde aus und ich wüsste jetzt auch nicht wie ich das "sauber" machen kann... aber wenn es performanter wäre... hätte ich ja schon was "gewonnen".

  • Da _IENavigate und _IELoadWait jeweils unter 1 Sekunde dauerte, sollte man noch _IEGetObjById messen.
    Irgendwie müssen die 4-5 Stunden ja zusammenkommen. _IENavigate und _IELoadWait dauern mit einem gemittelten Gesamtwert von 850 ms weniger als 1 Stunde.


    In den Raum gefragt (quick & dirty)

    Du kannst natürlich ein Controlskript erstellen, das eine beliebige Anzahl an Arbeitsskripten (im Prinzip Dein bisheriges Skript) startet und jeweils als Parameter den Index für den Startlink sowie die Anzahl der Links übergibt.

    Die Ergebnisse schreibt jedes Arbeitsskript in eine eigene Datei.

    Der Start des Arbeitsskriptes bekommt jeweils die PID des Prozesses zurück. Dieser wird in enem Array gespeichert.

    Das Controlskript prüft die Arbeitsprozesse anhand der PID auf Existenz. Wenn alle beendet sind, dann kann das Controlscript die Ergebnisse zu einer Gesamtergebnisdatei zusammenkopieren (falls notwendig).

  • Danke, habs mal angefügt.


    _IEGetObjById dauerte 9.2462

    _Stringbetween($oDivArticle.outerhtml) #1 dauert 0.4115

    _Stringbetween($oDivArticle.outerhtml) #2 dauert 0.3141

    _Stringbetween($oDivArticle.outerhtml) #3 dauert 0.3848

  • Das erhöht die Durchlaufzeit aber nur um etwas mehr als 10 ms. D.h. wir sind bei 4500 Durchläufen immer noch bei gut eienr Stunde.

    Kann es sein, dass die Durchlaufzeiten erheblich schwanken? Vielleicht sollte man mal für 50 Durchläufe die jeweilgie Gesamtzeit messen.

    Kannst Du bitte das aktuelle Skript posten?

  • Das erhöht die Durchlaufzeit aber nur um etwas mehr als 10 ms. D.h. wir sind bei 4500 Durchläufen immer noch bei gut eienr Stunde.

    Kann es sein, dass die Durchlaufzeiten erheblich schwanken? Vielleicht sollte man mal für 50 Durchläufe die jeweilgie Gesamtzeit messen.

    Kannst Du bitte das aktuelle Skript posten?

    Ich habe mich vertan in meinem ersten Post, ich sehe das erst jetzt, - ich meine 14.500 Abfragen, nicht "nur" 4.500. Sorry


    Grad mal laufen lassen, bei 100 Abfragen bin ich bei 112,1 Sekunden.


  • Ich probiere mal den Ansatz mit Controller/Worker Skript.

    Sobald ich was habe, poste ich hier

  • Ich probiere mal den Ansatz mit Controller/Worker Skript.

    Sobald ich was habe, poste ich hier

    Das ist super nett, vielen Dank!


    Eine weitere Frage habe ich noch, nach ca 400 Abfragen, wirft mir der EXplore immer eine Fehlermeldung, dass es ein Problem mit der Seite gab und diese neu geladen werden musste.

    Das ist ja ok, allerdings crashed dann dort das Script., weil er ja kein HTML mehr abrufen kann.

    Kann ich das umgehen? Also sowas wie ein on Error > return ?


    $aArray = _Stringbetween($oDivArticle.outerhtml, 'class="ampelbox ampelbox_', '" id="ampel1"')

    $aArray = _Stringbetween($oDivArticle^ ERROR

  • Ja, hierzu benötigst Du einen COM error handler. IE bringt die Möglichkeit für einen COM error handler mit.

  • Ja, hierzu benötigst Du einen COM error handler. IE bringt die Möglichkeit für einen COM error handler mit.

    Danke,


    ich habs jetzt "einfach" so gelöst...


    Code
        $oDivArticle = _IEGetObjById($oIE, "artikel_" & $ID_Split[1])
        If @error Then
            $i = $i - 1
            _IEQuit($oIE)
            $oIE = _IECreate($Link, 0, 0, 1, 0)
            ContinueLoop
        EndIf
  • Wenn ich das richtig verstanden habe:

    - es existiert eine Liste mit den Abfragen, die du vornehmen möchtest als csv-Datei

    - du iterierst durch die Datei, selektierst den abzufragenden Wert und rufst damit eine Web-Site auf

    - du wertest den Seiteninhalt aus und schreibst die Ergebnisse in dieselbe csv-Datei zurück


    1. Du hast die Daten in der csv in einer Form gespeichert, die du nur durch Zerlegen für eine Abfrage nutzen kannst

    2. Du hast > 4000 Datensätze - die du Zerlegen und beim Schreiben neu Erstellen musst - das frisst Zeit

    All das schreit förmlich nach der Verwendung einer Datenbank. Ob du MySQL oder SQLite verwendest ist da eher Geschmackssache, da du allein darauf zugreifst, ist SQLite hier völlig ausreichend.

    Vorteile der Datenbank:

    - Nur 1 Lesezugriff beim Laden der DB

    - Nur ein Schreibzugriff beim Schließen der DB

    - Alles andere sind direkte Speicheroperationen

    3. Ich würde zumindest versuchen, ob ich mit der direkten Auswertung des gesamten html der geladenen Seite mittels StringRegEx nicht schneller bin als über die IE-Operationen. D.h. ich würde komplett auf die _IE-Funktionen verzichten, stattdessen die Seiten mit InetRead auslesen (BinaryToString() nicht vergessen).

    4. Eine weitere Überlegung wäre das Splitten auf z.B. 4 Teile der Datensätze. Zur Abfrage startest du dann parallel 4 kompilierte Skripts.


    EDIT:

    Falls die Daten in Tabellen vorliegen ist es evtl. eine Möglichkeit mittels Excel Webanfragen (<Daten> <Externe Daten>) zu erstellen. Das machst du einmal für jede Tabelle und brauchst dann nur noch aktualisieren (mit VBA im Hintergrund lässt sich das auch automatisieren). Selbst wenn jede Abfrage eine Tabelle ist und pro Aktualisierung 1s draufgeht, wäre die Gesamtzeit mit 1 1/4 Stunden immer noch deutlich schneller als deine bisherige Abfrage.

  • 14.500 Abfragen

    NB: Im Post #14 spricht Leaves von 14500 Abfragen (4500 war ein Tippfehler). Darum ist die Gesamtlaufzeit 4-5 Stunden.