1. Dashboard
  2. Mitglieder
    1. Letzte Aktivitäten
    2. Benutzer online
    3. Team
    4. Mitgliedersuche
  3. Forenregeln
  4. Forum
    1. Unerledigte Themen
  • Anmelden
  • Registrieren
  • Suche
Alles
  • Alles
  • Artikel
  • Seiten
  • Forum
  • Erweiterte Suche
  1. AutoIt.de - Das deutschsprachige Forum.
  2. Mitglieder
  3. SOLVE-SMART

Beiträge von SOLVE-SMART

  • INI Eintragen

    • SOLVE-SMART
    • 30. Januar 2023 um 17:57

    Hi Alina ,

    Zitat von Alina

    Lass dich nicht abhalten, :/ junger Mann. :D

    Danke für das Kompliment, so jung bin ich leider auch nicht mehr 😅 .
    Aber ich erinnere meine Frau mal daran 😁 .

    Viele Grüße
    Sven

  • Artikelpreise aus Onlinekatalog in Rechnungsprogramm oder .xlsx

    • SOLVE-SMART
    • 30. Januar 2023 um 17:55

    Hi Swiffer,


    eine ausführliche Antwort folgt heute oder morgen 🤞 . Habe es zur Kenntnis genommen, aber gerade keine Zeit es ausführlich zu beschreiben.
    Bis dann.

    Viele Grüße
    Sven

  • SciTE - Commit & Push der aktuellen Datei

    • SOLVE-SMART
    • 30. Januar 2023 um 17:54

    Hi BugFix ,

    dies eine schöne Möglichkeit für SciTE, Danke 👍 .
    Für alle die die kein SciTE nutzen, kann auch der Weg über die Git Aliases genutzt werden, da kann man sich auch Git-Befehle kombinieren 😀 .

    Viele Grüße
    Sven

  • Git Repo in nicht leeren aktuellen Ordner klonen/darauf verlinken

    • SOLVE-SMART
    • 30. Januar 2023 um 13:13

    Hi BugFix ,


    ja es würde ein Hinweis kommen, dass der Ordner bereits vorhanden ist und nicht leer ist, daher bricht dies ab.
    An sich wirst du dir nichts so einfach zerschießen können, denn dafür ist GIT clever genug um dir Warnungen zu geben und auch die entsprechenden Vorschläge.

    Trotzdem kannst du ja beim ersten Test deinen Ordner kopieren (Backup), nur für den Fall der Fälle 😅 .

    Für dein Szenario konkret (so mache ich das bisher immer, ohne Probleme):

    Code
    git init
    git remote add origin https://github.com/BugFix/Test.git
    git fetch
    git checkout main -f
    git branch --set-upstream-to origin/main
    • Wenn du ältere Repos auf GitHub hast, dann musste du sehr wahrscheinlich master anstatt main als branch verwenden.
    • Ausgehend vom Verzeichnis, in das du clonen möchtest. Also direkt im Verzeichnis stehend.
    • Du kannst auch git fetch mit git pull (dritte Zeile) austauschen, allerdings mache dies lieber hinterher.
    • Ich nutze in diesem Beispiel die HTTPS clone Variante, Kanashius die SSH Variante. Einfach nur als Hinweis, beides geht natürlich.

    Viele Grüße
    Sven

  • Artikelpreise aus Onlinekatalog in Rechnungsprogramm oder .xlsx

    • SOLVE-SMART
    • 29. Januar 2023 um 09:53

    Hi Swiffer,

    freut mich das es dir zusagt 🤝 .

    Die eigentliche Automatisierung der Webseite ist gar nicht so sehr komplex. Die Abhängigkeiten des WebDriver sowie die vielen Vorbedingungen, welche zu erfüllen sind bevor man wirklich zur Seite navigieren kann und loslegen kann, dies ist komplexer, ja. Da lässt sich nicht viel machen. Allerdings kann man das Gerüst (das schaffen der Vorbedingungen) ja nun immer wieder verwenden 😀 .

    Wenn es an der Seite Anpassungen geben sollte und du nicht mehr die Ergebnisse bekommst, welche du erwartest, dann musst du bestenfalls erstmal nur an die XPath-Selectoren (XPath-Ausdrücke) heran. Wenn es mehr Änderungen geben sollte, an den Ablauf auch noch. Erfahrungsgemäß ändern sich solche Seiten aber nicht sehr oft (selten).

    Wenn es soweit kommen sollte, gib bitte einfach Bescheid oder versuche selbst wie weit du kommst. Eine ausführliche Erklärung "wie", würden den Rahmen sprengen. Daher habe ich nur das kommentiert, was man auch gut fassen kann ohne zu viele Insights zu haben/zu kennen.

    Wenn es bei dir funktioniert und alles gut ist, dann schließe gerne diesen Thread hier (auf erledigt) setzen. Falls dann später noch was aufkommt, mach' einfach einen neuen auf 👍 .

    Viele Grüße

    Sven

  • INI Eintragen

    • SOLVE-SMART
    • 27. Januar 2023 um 14:36

    Hi Alina ,

    wunderbar, Danke dir 👍 .

    pasted-from-clipboard.png

    Funktioniert wie erwartet. Allerdings bin ich mir nicht sicher, ob ich persönlich damit schneller wäre, also wenn ich die Sektion und das Key-Value Paar selbst erstelle.
    Trotzdem 'ne feine Sache für Nutzer die ggf. kaum Erfahrung mit INIs haben 🤝 , "Tak".

    Als Verbesserungsvorschlag sehe ich hier, dass gleich mehrere Sektionen und Key-Value Paare angelegt werden könnten, dann rockt das richtig 😅 .

    Alina: Ist dieser Thread ggf. etwas für diesen Thread? Vielleicht kann man, ( BugFix bspw.), die beiden verbinden? Oder meinst du Alina, dass es ein separater Kontext ist und bleiben soll?

    Viele Grüße
    Sven

  • Artikelpreise aus Onlinekatalog in Rechnungsprogramm oder .xlsx

    • SOLVE-SMART
    • 26. Januar 2023 um 21:44

    Hi Swiffer 👋 ,

    hier nun mein Vorschlag, für deine Website Automatisierung/Steuerung richner.teamonline.ch, bzw. für die Anforderung Daten der Website in eine CSV Datei zu überführen.

    AutoIt
    #AutoIt3Wrapper_AU3Check_Stop_OnWarning=y
    #AutoIt3Wrapper_Run_Au3Stripper=y
    #AutoIt3Wrapper_UseUpx=n
    #Au3Stripper_Parameters=/sf /sv /mo /rm /rsln
    
    Opt('MustDeclareVars', 1)
    
    #include-once
    #include <File.au3>
    #include "..\lib\au3WebDriver\wd_helper.au3"
    #include "..\lib\au3WebDriver\wd_capabilities.au3"
    
    
    
    ; initialization ---------------------------------------------------------------
    Global Const $sDriver         = 'Firefox' ; Chrome|Firefox
    Global Const $bIsHeadlessMode = False     ; False|True
    Global Const $iDelay          = 300       ; Verzögerung als Unterstützung für ein robustes Warteverhalten (Seitenaufbau, Klicks, Texte)
    Global $sSession              = Null
    
    
    
    ; processing -------------------------------------------------------------------
    _GetNewestDriver()  ; Dient zum aktualisieren des WebDrivers, kann später auskommentiert werden
    _SetLogLevel()      ; Log level auf error ($_WD_DEBUG_Error) reicht meiner Meinung nach, kann natürlich variiert werden
    _SetupDriver()      ; Session für chrome oder firefox (WebDriver) erstellen
    
    _Actions()          ; Steuerung der Artikel-mit-Preise Webseite
    
    _TeardownDriver()   ; WebDriver wieder herunterfahren
    
    
    
    ; setup and teardown functions -------------------------------------------------
    Func _GetNewestDriver()
        _WD_UpdateDriver(StringLower($sDriver), _PathFull('..\util\webDriver'))
    EndFunc
    
    Func _SetLogLevel()
        ;~ $_WD_DEBUG = $_WD_DEBUG_None ; no logging
        $_WD_DEBUG = $_WD_DEBUG_Error   ; logging in case of Error
        ;~ $_WD_DEBUG = $_WD_DEBUG_Info ; logging with additional information
        ;~ $_WD_DEBUG = $_WD_DEBUG_Full ; logging with full details for developers
    EndFunc
    
    Func _SetupDriver()
        _SetDriverOptions()
    
        _WD_Startup()
        _WD_CapabilitiesStartup()
    
        Local $sCapabilities = _
            (StringLower($sDriver) == 'chrome') _
                ? _CreateChromeDriverCapabilities() _
                : _CreateFirefoxDriverCapabilities()
    
        $sSession = _WD_CreateSession($sCapabilities)
    EndFunc
    
    Func _SetDriverOptions()
        Local Const $sDriverExe = _
            (StringLower($sDriver) == 'chrome') _
                ? 'chromedriver.exe' _
                : 'geckodriver.exe'
    
        Local Const $sDriverPath        = _PathFull('..\util\webDriver')
        Local Const $sDriverExeFilePath = $sDriverPath & '\' & $sDriverExe
    
        Local Const $iPort = _
            (StringLower($sDriver) == 'chrome') _
                ? 9515 _
                : 4444
    
        Local Const $sDriverParams = _
            (StringLower($sDriver) == 'chrome') _
                ? '--verbose --log-path="' & $sDriverPath & '\chromedriver.log"' _
                : '--log trace'
    
        _WD_Option('Driver', $sDriverExeFilePath)
        _WD_Option('Port', $iPort)
        _WD_Option('DriverParams', $sDriverParams)
    EndFunc
    
    Func _CreateChromeDriverCapabilities()
        _WD_CapabilitiesAdd('alwaysMatch', 'chrome')
        _WD_CapabilitiesAdd('w3c', True)
        _WD_CapabilitiesAdd('excludeSwitches', 'enable-automation')
        _WD_CapabilitiesAdd('args', '--window-size=1366,768')
    
        If $bIsHeadlessMode Then
            _WD_CapabilitiesAdd('args', '--headless')
        EndIf
    
        Return _WD_CapabilitiesGet()
    EndFunc
    
    Func _CreateFirefoxDriverCapabilities()
        _WD_CapabilitiesAdd('alwaysMatch', 'firefox')
        _WD_CapabilitiesAdd('browserName', 'firefox')
        _WD_CapabilitiesAdd('acceptInsecureCerts', True)
        _WD_CapabilitiesAdd('binary', 'C:\Program Files\Mozilla Firefox\firefox.exe') ; Ggf. einmalig diesen Pfad anpassen
        _WD_CapabilitiesAdd('args', '--window-size=1366,768')
    
        If $bIsHeadlessMode Then
            _WD_CapabilitiesAdd('args', '--headless')
        EndIf
    
        Return _WD_CapabilitiesGet()
    EndFunc
    
    Func _TeardownDriver()
        _WD_DeleteSession($sSession)
        _WD_Shutdown()
    EndFunc
    
    
    
    ; website functions ------------------------------------------------------------
    Func _Actions()
        Local Const $sCsvFilePath = _CreateArticlesAndPricesCsvFile() ; CSV Datei anlegen
    
        _OpenArticlesWebsite()                                        ; Webseite öffnen
    
        Local Const $iMaxSiteCount = _GetPaginationMaxSiteCount()     ; Anzahl der Seiten ermitteln, durch die navigiert werden muss,
                                                                      ; um alle Artikel/Preise zu berücksichtigen (nicht nur die der ersten Seite)
    
        For $i = 1 To $iMaxSiteCount - 1 Step 1                       ; Hier "- 1" da wir uns bereits auf der ersten Seite befinden
            Local $aListOfArticles          = _GetListOfArticles()    ; Artikel der jeweiligen Seite holen
            Local $aListOfPrices            = _GetListOfPrices()      ; Preise der jeweiligen Seite holen
    
            ; Dieser Schritt dient nur der Sicherheit, dass zu jedem Artikel auch ein dazugehöriger Preis gefunden wurde
            Local $aListOfArticlesAndPrices = _VerifyArticleCountAndPriceCountMatches($aListOfArticles, $aListOfPrices)
    
            ; CSV Datei mit gefundenen Werte füllen
            _WriteArticlesAndPricesToCsvFile($sCsvFilePath, $aListOfArticles, $aListOfPrices)
            _ChooseNextArticlePage()                                  ; Zur nächsten Seite navigieren
                                                                      ; und von vorn (Daten sammeln und in CSV schreiben)
        Next
    EndFunc
    
    Func _CreateArticlesAndPricesCsvFile()
        Local Const $sFilePath       = @ScriptDir & '\' & @YEAR & @MON & @MDAY & '-' & @HOUR & @MIN & @SEC & '-artikelnummer-verkaufspreis.csv'
        Local Const $sCsvColumnNames = 'Artikelnummer;Verkaufspreis' & @CRLF
    
        _WriteFile($sFilePath, $sCsvColumnNames)
    
        Return $sFilePath
    EndFunc
    
    Func _OpenArticlesWebsite()
        _NavigateTo('https://richner.teamonline.ch/waschtische-bidets-badezimmermoebel/aufsatzwaschtische-keramik')
    EndFunc
    
    Func _GetPaginationMaxSiteCount()
        Local Const $sPaginationTextSelector = '(//ul[@class="pagination"])[1]/li[contains(@class, "label")]'
    
        Local Const $sPaginationText             = _GetElementText($sPaginationTextSelector)
        Local Const $sRegExPatternOfMaxSiteCount = ' von (\d+)'
        Local Const $iReturnMatchesFlag          = 1
    
        Return StringRegExp($sPaginationText, $sRegExPatternOfMaxSiteCount, $iReturnMatchesFlag)[0]
    EndFunc
    
    Func _GetListOfArticles()
        Local Const $sArticleDescriptionSelector = '//h6[@class="product-itemnumber-desc"]'
    
        Local $aListOfElementsTexts = _GetElementsTexts($sArticleDescriptionSelector)
    
        Return _RemoveUnnecessaryTextsFromList($aListOfElementsTexts)
    EndFunc
    
    Func _RemoveUnnecessaryTextsFromList($aList)
        Local Const $iCount = _GetCount($aList)
    
        For $i = 0 To $iCount Step 1
            $aList[$i] = StringReplace($aList[$i], 'Artikel-Nr.: ', '')
            $aList[$i] = StringReplace($aList[$i], 'Farbe: ',       '')
            $aList[$i] = StringReplace($aList[$i], 'Ausführung: ',  '')
            $aList[$i] = StringReplace($aList[$i], @LF, '')
        Next
    
        Return $aList
    EndFunc
    
    Func _GetListOfPrices()
        Local Const $sArticlePriceSelector = '//div[@class="product-price "]/span'
    
        Return _GetElementsTexts($sArticlePriceSelector)
    EndFunc
    
    Func _VerifyArticleCountAndPriceCountMatches($aArticles, $aPrices)
        If _GetCount($aArticles) == _GetCount($aPrices) Then
            Return
        EndIf
    
        Local Const $iErrorIconFlag    = 16
        Local Const $sTimeoutInSeconds = 10
        Local Const $sErrorMessage     = 'Anzahl gefundener Artikel und die Anzahl der gefundenen Preise stimmt nicht überein.'
    
        MsgBox($iErrorIconFlag, 'Error', $sErrorMessage, $sTimeoutInSeconds)
    
        _TeardownDriver() ; WebDriver vorzeitig herunterfahren (bei Bedarf auskommentieren)
    EndFunc
    
    Func _WriteArticlesAndPricesToCsvFile($sFile, $aArticles, $aPrices)
        For $i = 0 To _GetCount($aArticles) Step 1
            _AppendToFile($sFile, $aArticles[$i] & ';' & $aPrices[$i] & @CRLF)
        Next
    EndFunc
    
    Func _ChooseNextArticlePage()
        Local Const $sPaginationArrowNextSelector = '(//ul[@class="pagination"])[1]//li[@class="arrow next "]'
    
        _ClickElement($sPaginationArrowNextSelector)
    EndFunc
    
    
    
    ; webdriver functions ----------------------------------------------------------
    Func _NavigateTo($sUrl)
        _WD_Navigate($sSession, $sUrl)
        _WD_LoadWait($sSession, $iDelay)
    EndFunc
    
    Func _FindElement($sSelector)
        Local $sElement = _WD_FindElement($sSession, $_WD_LOCATOR_ByXPath, $sSelector)
        If @error <> $_WD_ERROR_Success Then
            ConsoleWrite('Error for XPath selector ''' & $sSelector & '''.' & @CRLF)
            _TeardownDriver() ; WebDriver vorzeitig herunterfahren (bei Bedarf auskommentieren)
        EndIf
    
        Return $sElement
    EndFunc
    
    Func _FindElements($sSelector)
        Return _WD_FindElement($sSession, $_WD_LOCATOR_ByXPath, $sSelector, Default, True)
    EndFunc
    
    Func _WaitFor($sSelector)
        Local Const $iTimeoutInMilliseconds = 5000
        Local Const $iElementVisibleFlag    = 1
    
        _WD_WaitElement($sSession, $_WD_LOCATOR_ByXPath, $sSelector, $iDelay, $iTimeoutInMilliseconds, $iElementVisibleFlag)
    EndFunc
    
    Func _GetElementText($sSelector)
        _WaitFor($sSelector)
    
        Return _WD_ElementAction($sSession, _FindElement($sSelector), 'text')
    EndFunc
    
    Func _GetElementsTexts($sSelector)
        Local Const $aListOfElements = _FindElements($sSelector)
        Local Const $iCount          = _GetCount($aListOfElements)
    
        Local $aListOfElementsTexts[$iCount + 1]
    
        For $i = 0 To $iCount Step 1
            $aListOfElementsTexts[$i] = _WD_ElementAction($sSession, $aListOfElements[$i], 'text')
        Next
    
        Return $aListOfElementsTexts
    EndFunc
    
    Func _ClickElement($sSelector)
        _WaitFor($sSelector)
        _WD_ElementAction($sSession, _FindElement($sSelector), 'click')
    EndFunc
    
    
    
    ; helper functions -------------------------------------------------------------
    Func _WriteFile($sFile, $sText)
        Local Const $iUtf8WithoutBomAndOverwriteCreationMode = 256 + 2 + 8
    
        Local $hFile = FileOpen($sFile, $iUtf8WithoutBomAndOverwriteCreationMode)
        FileWrite($hFile, $sText)
        FileClose($hFile)
    EndFunc
    
    Func _GetCount($aList)
        Return UBound($aList) - 1
    EndFunc
    
    Func _AppendToFile($sFile, $sText)
        Local Const $iUtf8WithoutBomAndAppendMode = 256 + 1
    
        Local $hFile = FileOpen($sFile, $iUtf8WithoutBomAndAppendMode)
        FileWrite($hFile, $sText)
        FileClose($hFile)
    EndFunc
    Alles anzeigen
    • Die wichtigsten Stellen habe ich kommentiert.
      • Ich hoffe das reicht dir, ansonsten sind die Funktionen und Variablen treffend benannt (wie im post vorher bereits angekündigt 😅).
      • Frage bitte gerne nach, wenn dir irgendwas unklar sein sollte 🤝 .
    • Fehlerbehandlung ist nur minimal vorhanden, da sobald die Seite geladen ist (im WebDriver, chrome oder firefox), sie recht stabil ist und daher schätze ich den Bedarf dazu als gering ein.
      • Der Ablauf diesbzgl. kann noch ausgebaut/robuster gemacht werden (wirst du sehen ob du da mehr brauchst oder nicht).
      • Gerne auch hierzu nachfragen bei Bedarf.
    • Derzeit besteht eine leichte Verzögerung von 300 ms $iDelay, Zeile 18, für das Interagieren mit den Website-Elementen.
      • Beim lesen von Texten (Artikel und Preise etc.) sowie bei Klicks ist dies so. Kannst du gern noch anpassen, doch zu weniger als 150 ms würde ich nicht raten.
      • Dies dient der Robustheit der Ausführung. Es wird damit etwas langsamer, doch darauf kommt es dir sicherlich nicht an oder?
    • 💡 Eine Unschönheit ist, dass ich den automatischen Lauf im headless Modus ($bIsHeadlessMode), Zeile 17, nicht erfolgreich umsetzen konnte.
      • Also dafür müsste ich noch etwas Zeit aufwenden um das "Warum" zu klären und dies dann zu fixen. Jedoch auf Grund deiner Ausführungen sehe ich auch hier den Bedarf erstmal nicht.
      • Wie das ganze im headless Modus funktioniert, ist aber vorbereitet und du kannst sehen wie es sein müsste.
      • Falls du doch möchtest, dass der Browser unsichtbar seine Arbeit verrichtet und dein Skript die CSV anlegt, gib Bescheid. Dann setze ich mich vielleicht nochmal ran 🤝 .
    • Randnotiz: Im kommenden WebDriver Tutorial wird die Strukturierung nochmal anders sein.

    Das Skript allein, ist so nicht lauffähig. Alle Abhängigkeiten1, welche benötigt werden, inklusive des Main.au3 Skriptes können hier heruntergeladen werden.

    Das Ergebnis, der Ausführung ist, dass eine CSV Datei mit den gefundenen Artikelnummern und Verkaufspreisen angelegt wird. Also Beispiel für den heutigen Lauf:

    20230126-171516-artikelnummer-verkaufspreis.csv
    Code
    Artikelnummer;Verkaufspreis
    234057100242;893.00
    234057100244;998.00
    234064100242;942.00
    234064100244;1'047.00
    234051100242;439.00
    234051100244;547.00
    234072100242;535.00
    234072100244;640.00
    212144242;770.00
    212144244;875.00
    212149242;842.00
    212149244;947.00
    212156241;806.00
    212156243;911.00
    212157241;842.00
    212157243;947.00
    213120100241;330.00
    213120100243;435.00
    234551100;683.00
    234552100;974.00
    234155100183;710.00
    234155100184;835.00
    234156100183;767.00
    234156100184;892.00
    234157100183;668.00
    234157100184;793.00
    234158100183;725.00
    234158100184;850.00
    234161100183;835.00
    234161100184;959.00
    234162100183;891.00
    234162100184;1'015.00
    234163100183;851.00
    234163100184;977.00
    234164100183;909.00
    234164100184;1'035.00
    234188100183;484.00
    234188184;609.00
    234189100183;540.00
    234189184;665.00
    234190100183;519.00
    234190184;644.00
    234191100183;575.00
    234191184;700.00
    234192100183;608.00
    234192184;733.00
    234193100183;665.00
    234193184;790.00
    234194100183;625.00
    234194184;750.00
    234195100183;681.00
    234195184;806.00
    234196100183;608.00
    234196184;733.00
    234197100183;665.00
    234197184;790.00
    234198100183;625.00
    234198184;750.00
    234199100183;681.00
    234199184;806.00
    234171242;909.00
    234171244;1'034.00
    234172242;781.00
    234172244;909.00
    234173242;790.00
    234173244;918.00
    234174242;926.00
    234174244;1'051.00
    234176100244;989.00
    234177100244;1'153.00
    212650100242;326.00
    212650100244;437.00
    212651100241;326.00
    212651100243;437.00
    212652100241;326.00
    212652100243;437.00
    212653100242;352.00
    212653100244;461.00
    212654100241;371.00
    212654100243;478.00
    212655100241;371.00
    212655100243;478.00
    212656100242;362.00
    212656100244;473.00
    212657100241;352.00
    212657100243;461.00
    212658100241;352.00
    212658100243;461.00
    212659100241;380.00
    212659100243;484.00
    212660100241;380.00
    212660100243;484.00
    212661100242;376.00
    212661100244;480.00
    212662100241;390.00
    212662100243;497.00
    212663100241;390.00
    212663100243;497.00
    212699100241;329.00
    212699100243;426.00
    292145;926.00
    292146;926.00
    292147;926.00
    292148;926.00
    292149;926.00
    292150;926.00
    292151;926.00
    292152;813.00
    292153;669.00
    212892100242;351.00
    212625241;560.00
    212625242;560.00
    212625100293;694.00
    212625100294;694.00
    212627241;1'104.00
    212627242;1'104.00
    212627100293;1'238.00
    212627100294;1'238.00
    212900241;488.00
    212900242;488.00
    212900100293;626.00
    212900100294;626.00
    Alles anzeigen

    Dateiname ist @ScriptDir & '\' & @YEAR & @MON & @MDAY & '-' & @HOUR & @MIN & @SEC & '-artikelnummer-verkaufspreis.csv'. Anpassbar in Zeile 142.

    Viel Erfolg Swiffer damit 😀 .

    Viele Grüße

    Sven

    1 Der benötigte WebDriver (entweder Chrome oder Firefox), wird via "_WD_UpdateDriver()" heruntergeladen. Daher ist dieser nicht im verlinktem Verzeichnis vorhanden.

  • Artikelpreise aus Onlinekatalog in Rechnungsprogramm oder .xlsx

    • SOLVE-SMART
    • 26. Januar 2023 um 12:26

    Kurzes Update Swiffer:
    Ich plane dir heute, morgen oder übermorgen meinen fertigen Vorschlag (eine WebDriver Variante) zu kommen zu lassen. Ähnlich wie bei diesem Thread post für Windi, wird das "Wie" per Kommentare beschrieben sein und die Funktionsnamen sowie Variablennamen entsprechend aussagekräftig sein.

    Hilf mir nochmal bitte kurz:
    Welchen Browser nutzt du? Ich habe dies glaube ich schon mal gefragt, finde es aber auf die Schnelle nicht 😅 .

    Viele Grüße
    Sven

  • Webdriver xPath iFrames usw.

    • SOLVE-SMART
    • 25. Januar 2023 um 15:51

    Freut mich Werner, dass es auch bei dir gut läuft => so sollte es sein 😀 .

    Was Opt('MustDeclareVars', 1) angeht kann ich sagen ja, es geht auch ohne, doch mein Entwicklerherz sagt nein 😅 .
    Also dies sagt, dass du alle Variablen mit einem scope (bspw. Local oder Global (global immer nur außerhalb von Funktionen)) deklarieren musst, bevor du sie verwenden kannst. Dies dient der Fehlervermeidung unter gewissen Umständen. Wenn du also darauf verzichten willst - kein Problem. So lange du deine Variablen unter Kontrolle hast, sollte es wenige/keine Probleme mit sich bringen. Wenn du es strikt machst, daher mein Ansatz es einzuschalten, dann kannst du eben nicht in gewisse Probleme laufen.

    💡 Lösche einfach die Zeile heraus oder passe alle Stellen die dir als Fehlermeldungen angezeigt werden an. Wenn du das nächste Mal ein Programm schreibst, dann nutze die Option vielleicht gleich von Anfang an, dann wird du nicht wieder vor dieser Entscheidung stehen müssen 😀 .

    Übrigens:
    Wenn dies deiner Anforderung entspricht (also mein Skript, die Abhängigkeiten etc.), dann schließe gern diesen Thread hier (auf erledigt setzen). Bei Bedarf mache dann einfach einen neuen auf.

    Viele Grüße
    Sven

  • Webdriver xPath iFrames usw.

    • SOLVE-SMART
    • 24. Januar 2023 um 23:28

    Hi Windi (Werner) 👋 ,

    hier nun mein Vorschlag, für deine Website Automatisierung/Steuerung mydrive.tomtom.com.

    AutoIt
    #AutoIt3Wrapper_AU3Check_Stop_OnWarning=y
    #AutoIt3Wrapper_Run_Au3Stripper=y
    #AutoIt3Wrapper_UseUpx=n
    #Au3Stripper_Parameters=/sf /sv /mo /rm /rsln
    
    Opt('MustDeclareVars', 1)
    
    #include-once
    #include <File.au3>
    #include "..\lib\au3WebDriver\wd_helper.au3"
    #include "..\lib\au3WebDriver\wd_capabilities.au3"
    
    
    
    ; initialization ---------------------------------------------------------------
    Global Const $sDriver         = 'Firefox' ; Chrome|Firefox
    Global Const $bIsHeadlessMode = False     ; False|True
    Global Const $iDelay          = 1000      ; Nicht unter eine Sekunde gehen, da durch die Animationen das Skript nicht mehr robust wäre
    Global $sSession              = null
    
    
    
    ; processing -------------------------------------------------------------------
    _GetNewestDriver()  ; Dient zum Aktualisieren, kann später auskommentiert werden
    _SetLogLevel()      ; Log level auf error ($_WD_DEBUG_Error) reicht meiner Meinung nach, kann natürlich variiert werden
    _SetupDriver()      ; Session für chrome oder firefox (WebDriver) erstellen
    
    _Actions()          ; Steuerung der MyDriveTomTom Webseite
    
    _TeardownDriver()   ; WebDriver wieder herunterfahren
    
    
    
    ; setup and teardown functions -------------------------------------------------
    Func _GetNewestDriver()
        _WD_UpdateDriver(StringLower($sDriver), _PathFull('..\util\webDriver'))
    EndFunc
    
    Func _SetLogLevel()
        ;~ $_WD_DEBUG = $_WD_DEBUG_None  ; no logging
        $_WD_DEBUG = $_WD_DEBUG_Error ; logging in case of Error
        ;~ $_WD_DEBUG = $_WD_DEBUG_Info  ; logging with additional information
        ;~ $_WD_DEBUG = $_WD_DEBUG_Full  ; logging with full details for developers
    EndFunc
    
    Func _SetupDriver()
        _SetDriverOptions()
        _WD_Startup()
    
        Local $sCapabilities = _
            (StringLower($sDriver) == 'chrome') _
                ? _CreateChromeDriverCapabilities() _
                : _CreateFirefoxDriverCapabilities()
    
        $sSession = _WD_CreateSession($sCapabilities)
    EndFunc
    
    Func _SetDriverOptions()
        Local Const $sDriverExe = _
            (StringLower($sDriver) == 'chrome') _
                ? 'chromedriver.exe' _
                : 'geckodriver.exe'
    
        Local Const $sDriverPath = _PathFull('..\util\webDriver')
        Local Const $sDriverExeFilePath = $sDriverPath & '\' & $sDriverExe
    
        Local Const $iPort = _
            (StringLower($sDriver) == 'chrome') _
                ? 9515 _
                : 4444
    
        Local Const $sDriverParams = _
            (StringLower($sDriver) == 'chrome') _
                ? '--verbose --log-path="' & $sDriverPath & '\chromedriver.log"' _
                : '--log trace'
    
        _WD_Option('Driver', $sDriverExeFilePath)
        _WD_Option('Port', $iPort)
        _WD_Option('DriverParams', $sDriverParams)
    EndFunc
    
    Func _CreateChromeDriverCapabilities()
        _WD_CapabilitiesStartup()
    
        _WD_CapabilitiesAdd('alwaysMatch', 'chrome')
        _WD_CapabilitiesAdd('w3c', True)
        _WD_CapabilitiesAdd('excludeSwitches', 'enable-automation')
        _WD_CapabilitiesAdd('args', '--window-size=1366,768')
    
        If $bIsHeadlessMode Then
            _WD_CapabilitiesAdd('args', '--headless')
        EndIf
    
        Return _WD_CapabilitiesGet()
    EndFunc
    
    Func _CreateFirefoxDriverCapabilities()
        _WD_CapabilitiesStartup()
    
        _WD_CapabilitiesAdd('alwaysMatch', 'firefox')
        _WD_CapabilitiesAdd('browserName', 'firefox')
        _WD_CapabilitiesAdd('acceptInsecureCerts', True)
        _WD_CapabilitiesAdd('binary', 'C:\Program Files\Mozilla Firefox\firefox.exe') ; Ggf. einmalig diesen Pfad anpassen
        _WD_CapabilitiesAdd('args', '--window-size=1366,768')
    
        If $bIsHeadlessMode Then
            _WD_CapabilitiesAdd('args', '--headless')
        EndIf
    
        Return _WD_CapabilitiesGet()
    EndFunc
    
    Func _TeardownDriver()
        _WD_DeleteSession($sSession)
        _WD_Shutdown()
    EndFunc
    
    
    
    ; website functions ------------------------------------------------------------
    Func _Actions()
        _OpenMyDriveTomTomWebsite()                 ; Webseite öffnen
        _AcceptsCookieConsent()                     ; Cookie consent bestätigen
    
        Local Const $sUsername = 'abcabcb@email.de' ; Hier die richtige Email eintragen
        Local Const $sPassword = 'abcabcabcab'      ; Hier das richtige Passwort eintragen
    
        _LoginToMyDrive($sUsername, $sPassword)     ; Login
    
        ; Testdaten (55 Einträge)
        Local $aTableOfAddresses[][2] = _           ; Diese Testdaten müssen natürlich mit deinen Echtdaten ersetzt werden
            [ _
                ['Test Name Landhotel', 'Westfälische Str. 52 57368 Lennestadt'], _
                ['Test Name München',   'Landsberger Straße 10 80339 München'], _
                ['Test Name Nürnberg',  'Hermannstrasse 9 90439 Nürnberg'], _
                ['Test Name Berlin',    'Pohlstrasse 67 10785 Berlin'], _
                ['Test Name Köln',      'Aachener Straße 300 50933 Köln'], _
                ['Test Name 06 Berlin', 'Alt-Lübars 11 13469 Berlin'], _
                ['Test Name 07 Berlin', 'Am Großen Wannsee 69 14109 Berlin'], _
                ['Test Name 08 Berlin', 'Am Studio 16 12489 Berlin'], _
                ['Test Name 09 Berlin', 'Am Zeppelinpark 51 13591 Berlin'], _
                ['Test Name 10 Berlin', 'Andreasstraße 21a 10243 Berlin'], _
                ['Test Name 11 Berlin', 'Berkaer Straße 5 14199 Berlin'], _
                ['Test Name 12 Berlin', 'Berliner Allee 187 13088 Berlin'], _
                ['Test Name 13 Berlin', 'Boothstraße 1C 12207 Berlin'], _
                ['Test Name 14 Berlin', 'Boxhagener Straße 97 10245 Berlin'], _
                ['Test Name 15 Berlin', 'Daumstraße 63 13599 Berlin'], _
                ['Test Name 16 Berlin', 'Dessauer Straße 13 10963 Berlin'], _
                ['Test Name 17 Berlin', 'Drei-Linien-Weg 39 13125 Berlin'], _
                ['Test Name 18 Berlin', 'Emser Straße 40 12051 Berlin'], _
                ['Test Name 19 Berlin', 'Fabeckstraße 9 14195 Berlin'], _
                ['Test Name 20 Berlin', 'Flurweg 72d 12357 Berlin'], _
                ['Test Name 21 Berlin', 'Freystadter Weg 73 12489 Berlin'], _
                ['Test Name 22 Berlin', 'Grünbergallee 300 12526 Berlin'], _
                ['Test Name 23 Berlin', 'Güldenhofer Ufer 4 12437 Berlin'], _
                ['Test Name 24 Berlin', 'Havelchaussee 83A 14193 Berlin'], _
                ['Test Name 25 Berlin', 'Helene-Weigel-Platz 14 12681 Berlin'], _
                ['Test Name 26 Berlin', 'Hoppestraße 30 13409 Berlin'], _
                ['Test Name 27 Berlin', 'Kolmarer Straße 2 10405 Berlin'], _
                ['Test Name 28 Berlin', 'Kommandantenstraße 95 12205 Berlin'], _
                ['Test Name 29 Berlin', 'Lehmusstraße 38 12524 Berlin'], _
                ['Test Name 30 Berlin', 'Lotosweg 26 13467 Berlin'], _
                ['Test Name 31 Berlin', 'Ludwigsburger Weg 2 12247 Berlin'], _
                ['Test Name 32 Berlin', 'Müggelseedamm 300 12587 Berlin'], _
                ['Test Name 33 Berlin', 'Neukladower Allee 12 14089'], _
                ['Test Name 34 Berlin', 'Niederheideweg 25 13589 Berlin'], _
                ['Test Name 35 Berlin', 'Nonnendammallee 175 13599 Berlin'], _
                ['Test Name 36 Berlin', 'Osdorfer Straße 59 12207 Berlin'], _
                ['Test Name 37 Berlin', 'Pembabogen 1 13587 Berlin'], _
                ['Test Name 38 Berlin', 'Petunienweg 46 12357 Berlin'], _
                ['Test Name 39 Berlin', 'Porzer Straße 15 12524 Berlin'], _
                ['Test Name 40 Berlin', 'Réaumurstraße 39A 12207 Berlin'], _
                ['Test Name 41 Berlin', 'Rehbrücker Weg 3 14165 Berlin'], _
                ['Test Name 42 Berlin', 'Ribbecker Straße 7 10315 Berlin'], _
                ['Test Name 43 Berlin', 'Rudolfstraße 16 10245 Berlin'], _
                ['Test Name 44 Berlin', 'Schleizer Straße 67 13055 Berlin'], _
                ['Test Name 45 Berlin', 'Steinauer Straße 9 13125 Berlin'], _
                ['Test Name 46 Berlin', 'Straße 101 5 13125 Berlin'], _
                ['Test Name 47 Berlin', 'Tillmannsweg 5b 14109 Berlin'], _
                ['Test Name 48 Berlin', 'Trachenbergring 8 12249 Berlin'], _
                ['Test Name 49 Berlin', 'Waldstraße 73 12621 Berlin'], _
                ['Test Name 50 Berlin', 'Weisestraße 10 12049 Berlin'], _
                ['Test Name 51 Berlin', 'Wikingerufer 9a 10555 Berlin'], _
                ['Test Name 52 Berlin', 'Windenweg 58a 12357 Berlin'], _
                ['Test Name 53 Berlin', 'Windmühlenweg 11 13469 Berlin'], _
                ['Test Name 54 Berlin', 'Yorckstraße 74 10965 Berlin'], _
                ['Test Name 55 Berlin', 'Zeisigweg 18 12209 Berlin'] _
            ]
    
        _AddAddressesToFavorites($aTableOfAddresses) ; Adress- und Namensdaten in Favoriten eintragen
    EndFunc
    
    Func _OpenMyDriveTomTomWebsite()
        _NavigateTo('https://mydrive.tomtom.com/de_de/#mode=viewport+viewport=49.9071,7.8184,13,0,-0+ver=3')
    EndFunc
    
    Func _AcceptsCookieConsent()
        Local Const $sAcceptCookieSelector = '//button[@id="cookie_banner_allow_button"][text()="Akzeptieren"]'
    
        _ClickElement($sAcceptCookieSelector)
    EndFunc
    
    Func _LoginToMyDrive($sUsername, $sPassword)
        Local Const $sLoginButtonSelector = '//button[contains(@id, "-loginButton")][text()="Anmelden"]'
        Local Const $sIframeSelector      = '//iframe[@id="iFrameResizer0"]'
    
        _ClickElement($sLoginButtonSelector)
        _EnterIFrame($sIframeSelector)
    
        Local Const $sEmailInputSelector    = '//input[@id="IDToken1"][@name="username"]'
        Local Const $sPasswordInputSelector = '//input[@id="IDToken2"][@name="password"]'
        Local Const $sLoginInputSelector    = '//input[@id="loginButton"][@value="Anmelden"]'
    
        _SetElementText($sEmailInputSelector, $sUsername)
        _SetElementText($sPasswordInputSelector, $sPassword)
        _ClickElement($sLoginInputSelector)
    
        _LeaveIFrame()
    EndFunc
    
    Func _AddAddressesToFavorites($aTableOfAddresses)
        Local Const $sMyPlacesSelector    = '//div[@id="my_places_menu_item"][contains(., "Meine Orte")]'
        Local Const $sFavoritesSelector   = '//span[@id="my_places_favourites"][text()="Favoriten"]'
    
        _ClickElement($sMyPlacesSelector)
        _ClickElement($sFavoritesSelector)
    
        Local Const $sAddNewPlaceSelector             = '//div[@id="favourites_view_add_favourite_button"]//div[text()="Neuen Ort hinzufügen"]'
        Local Const $sAddressInputSelector            = '//input[@id="favourite_location_search_input_box"]'
        Local Const $sNameInputSelector               = '//div[@id="favourite_name_input_box"]/input'
        Local Const $sFirstSuggestionListItemSelector = '//div[@id="favourite_search_suggestions_panel"]//div[contains(@id, "list_item_address_0")]'
        Local Const $sDoneButtonSelector              = '//button[@id="favourite_add_done_btn"][text()="Fertig"]'
    
        Local Const $iAddressCount = Ubound($aTableOfAddresses) - 1
    
        For $i = 0 To $iAddressCount Step 1
            _ClickElement($sAddNewPlaceSelector)
    
            Local $sName    = $aTableOfAddresses[$i][0]
            Local $sAddress = $aTableOfAddresses[$i][1]
    
            ConsoleWrite($i & '/' & $iAddressCount & ' ==> ' & $sAddress & @CRLF)
    
            _SetElementText($sAddressInputSelector, $sAddress)
            _SetElementText($sNameInputSelector, $sName)
    
            _ClickElement($sFirstSuggestionListItemSelector, $sAddress)
            _ClickElement($sDoneButtonSelector)
        Next
    EndFunc
    
    
    
    ; webdriver functions ----------------------------------------------------------
    Func _NavigateTo($sUrl)
        _WD_Navigate($sSession, $sUrl)
        _WD_LoadWait($sSession, $iDelay)
    EndFunc
    
    Func _FindElement($sSelector, $sMessage = '')
        Local $sElement = _WD_FindElement($sSession, $_WD_LOCATOR_ByXPath, $sSelector)
        If @error <> $_WD_ERROR_Success Then
            ConsoleWrite($sMessage & ' ==> Error for XPath selector ''' & $sSelector & '''.' & @CRLF)
            _TeardownDriver() ; WebDriver vorzeitig herunterfahren (bei Bedarf auskommentieren)
        EndIf
    
        Return $sElement
    EndFunc
    
    Func _ClickElement($sSelector, $sMessage = '')
        _WaitFor($sSelector)
        _WD_ElementAction($sSession, _FindElement($sSelector, $sMessage), 'click')
    EndFunc
    
    Func _EnterIFrame($sSelector)
        _WD_FrameEnter($sSession, _FindElement($sSelector))
    EndFunc
    
    Func _SetElementText($sSelector, $sValue)
        _WaitFor($sSelector)
        _WD_ElementAction($sSession, _FindElement($sSelector), 'value', $sValue)
    EndFunc
    
    Func _LeaveIFrame()
        _WD_FrameLeave($sSession)
        Sleep($iDelay)
    EndFunc
    
    Func _WaitFor($sSelector)
        Local Const $iTimeoutInMilliseconds = 5000
        Local Const $iElementVisibleFlag    = 1
    
        _WD_WaitElement($sSession, $_WD_LOCATOR_ByXPath, $sSelector, $iDelay, $iTimeoutInMilliseconds, $iElementVisibleFlag)
    EndFunc
    Alles anzeigen
    • Die wichtigsten Stellen habe ich kommentiert.
      • Ich hoffe das reicht dir, ansonsten sind die Funktionen und Variablen treffend benannt.
      • Frage bitte gerne nach, wenn dir irgendwas unklar sein sollte 🤝 .
    • $sUsername und $sPassword sind nicht die Richtigen1.
    • Testdaten müssen mit deinen Echtdaten noch ausgetauscht werden.
    • Fehlerbehandlung ist nur minimal vorhanden, sehe den Bedarf tatsächlich eher gering.
      • Auch hierbei kann der Ablauf noch ausgebaut/robuster gemacht werden (wirst du sehen ob du da mehr brauchst oder nicht).
    • Derzeit ist die Ausführung der Klicks mit einer Verzögerung von einer Sekunde (1000ms) angelegt, da ansonsten die Animationen der Webseite die robuste Ausführung verhindern könnte.
      💡 500ms reicht auch, doch im headless ($bIsHeadlessMode) Modus empfehle ich bei dieser Seite 1000ms.
    • Randnotiz: Im kommenden WebDriver Tutorial wird die Strukturierung nochmal anders sein.

    Das Skript allein, ist so nicht lauffähig. Alle Abhängigkeiten2, welche benötigt werden, inklusive des Main.au3 Skriptes können hier heruntergeladen werden3.


    Viel Erfolg Werner damit 😀 .


    Viele Grüße
    Sven

    1 Als Hinweis für alle die, die dies komplett nachstellen wollen, bitte an Werner direkt wenden.

    2 Der benötigte WebDriver (entweder Chrome oder Firefox), wird via "_WD_UpdateDriver()" heruntergeladen. Daher ist dieser nicht im verlinktem Verzeichnis vorhanden.

    3 Achtung, auch wieder fake Login-Daten.

  • Deutsche Hilfe auf 3.3.16.1 updaten - mitmachen

    • SOLVE-SMART
    • 24. Januar 2023 um 16:01
    Zitat von Peter S. Taler

    [...] Ps.: Einmal passt Dir mein Schreibstil für Code nicht - dann vermisst Du ein Vorwort und Inhaltsverzeichnis - Oberlehrer konnte ich schon auf der Schule nicht leiden!

    Ich glaube wir finden sachlich einfach nicht zueinander Peter S. Taler 😔 . Müssen wir aber auch nicht unbedingt.
    Ich unterstelle uns beiden gute Absichten 😀 , nur in unterschiedlichen Ausführungen, Ideen und Ansprüchen.
    Daher ist es für mich in Ordnung wenn wir nicht einer Meinung sind. Streiten müssen wir jedoch wegen sowas nicht!

    Ich lass dich in Zukunft einfach machen Peter S. Taler und nutze die Zeit um Anderen hier im Forum zu helfen oder sie zu unterstützen.

    Viele Grüße
    Sven

  • Deutsche Hilfe auf 3.3.16.1 updaten - mitmachen

    • SOLVE-SMART
    • 24. Januar 2023 um 13:26

    Danke für deine Bemühungen Peter S. Taler 👍 .

    Ich nehme an, du willst später noch ein Inhaltsverzeichnis einfügen? Genau wie solche Kategorien wie ein Vorwort, an wen richtet sich das Buch, was kann man erwarten (was deckt das Buch ab, was nicht) usw.? Das wird eine ganze Menge Arbeit, um ein sachlich fundiertes Buch zu schreiben 🤔 .

    Viele Grüße
    Sven

  • Netzlaufwerk auf CurrentUser Share

    • SOLVE-SMART
    • 24. Januar 2023 um 10:39

    Ja Fuffi778,

    zumindest laut Hilfe wäre es so korrekt. Hier mal als Funktion dargestellt:

    AutoIt
    _MapNetworkDrive()
    
    Func _MapNetworkDrive()
        Local Const $sDevice        = 'K:'
        Local Const $sShare         = '\\xy.dummy.ch\' & @UserName & '$'
        Local Const $iMappingFlag   =  0
        Local Const $sDomainAndUser =  'domain\username'
        Local Const $sPassword      =  'password'
    
        DriveMapAdd($sDevice, $sShare, $iMappingFlag, $sDomainAndUser, $sPassword)
        If @error <> 0 Then
            ; Failure
        EndIf
    EndFunc
    Alles anzeigen

    Vielleicht hilft dir dies etwas besser beim Verständnis. Bzw. für den Fall, dass du etwas mehr Dynamic (Funktionsparameter bei Bedarf) brauchst. Weitere Shares, weitere User mit anderen Passwörtern etc.

    Viel Erfolg 🤞 .

    Viele Grüße
    Sven

  • SciTE - Fold / Expand mit Pattern für "Startzeile Faltbereich"

    • SOLVE-SMART
    • 24. Januar 2023 um 08:20
    Zitat von Moombas

    Ein Grund für mich es niemals zu nutzen :P

    Kaffeetassen gehören einfach nit in einen PC :D

    🤣 Jeder nach seiner Fasson Moombas. Gut für dich wenn du daran vorbei kommst, ich schaffe es beruflich nicht 🤪 .

    Viele Grüße
    Sven

  • Webdriver xPath iFrames usw.

    • SOLVE-SMART
    • 23. Januar 2023 um 21:56

    Alles klar Werner, dann ist mein Array oben also genau vertauscht? Erst Name, dann Adresse, okay - passe ich noch an.
    Die Angabe das es bis zu 100 Adressen sein können ist gut, dann Teste ich mal mit 75 und schaue wie es sich verhält.

    Viele Grüße
    Sven

  • Webdriver xPath iFrames usw.

    • SOLVE-SMART
    • 23. Januar 2023 um 21:05

    Hallo erneut Windi ,

    kannst du mir bitte mal ein Beispiel senden oder zumindest einen Auszug aus deiner Adresstabelle oder Adressliste geben?
    Also ich nehme folgendes an:

    • Neuen Ort hinzufügen
    • Adresse und Name eingeben
    • erste vorgeschlagene Adresse auswählen
    • Fertig button klicken

    läuft alles in einer Schleife, richtig? Also so würde ich es tun. Doch du kennst deinen fachlichen Ablauf und Kontext besser 😅 .

    Im Moment habe ich zum Test einfach nur ein Array (eine Dummy Tabelle) erstellt, die in der Schleife durchgearbeitet wird. Diese besteht einfach aus Adresse und Name (was ja optional ist):

    AutoIt
    Local $aTableOfAddresses[][2] = _
        [ _
            ['Westfälische Str. 52 57368 Lennestadt', 'Landhotel'], _
            ['Landsberger Straße 10 80339 München',   'Test München'], _
            ['Hermannstrasse 9 90439 Nürnberg',       'Test Nürnberg'], _
            ['Pohlstrasse 67 10785 Berlin',           'Test Berlin'], _
            ['Aachener Straße 300 50933 Köln',        'Test Köln'] _
        ]

    Wenn deine CSV deutlich abweicht, dann müsste ich das in meinem Test berücksichtigen, darum frage ich.

    • Abgesehen davon läuft es im Chrome bereits robust durch, auch im headless Modus. Aber Firefox muss ich noch fertig testen. Dann bekommst du meinen Vorschlag.
    • Doch zunächst brauche ich bitte eine Angabe von dir wie viele Adressen auf einmal eingepflegt werden sollen (etwa) und wie die CSV bzw. deine Daten aussehen (auch nur grob).

    Danke dir Werner 🤝 .

    Viele Grüße
    Sven

  • Deutsche Hilfe auf 3.3.16.1 updaten - mitmachen

    • SOLVE-SMART
    • 23. Januar 2023 um 20:07
    Zitat von Alina

    [...] Ein Buch ist immer gut aus meiner Sicht. Da kann man dann mal nachschlagen ohne onlien zu sein, man kann Notizen machen und Markierungen (farblich hinterlegen) tätigen. [...]

    Gut finde ich das auch, absolut Alina. Doch es braucht auch Abnehmer, die den initialen Aufwand rechtfertigen und noch wichtiger, die Pflege und Erweiterung des Buches. Da sehe ich eben aus gegebenen Fakten heraus, kaum eine Chance 😔 .

    Viele Grüße
    Sven

  • SciTE - Fold / Expand mit Pattern für "Startzeile Faltbereich"

    • SOLVE-SMART
    • 23. Januar 2023 um 20:05

    Hi BugFix ,

    ich bin begeistert ehrlich gesagt 😀 . Ich nutze zwar den ScITE Editor, wie du weißt, nicht mehr, dennoch finde ich es toll wie SciTE mit Lua interagiert bzw. andersherum.

    Super nett finde ich es auch von dir, dass du dir (wenn ich es richtig beobachtet und verfolgt habe) einen konkreten Thread zum Anlass genommen hast, um das ganze umzusetzen 👍 .

    Bei VSCode läuft eben fast alles was Extensions usw. angeht, über JavaScript (hatten wir schon das Thema). Danke aber für diese Arbeit und das Beispiel was mit Lua geht, denn ich muss mir unbedingt mal Lua genauer anschauen 🤝 .

    Viele Grüße
    Sven

  • Deutsche Hilfe auf 3.3.16.1 updaten - mitmachen

    • SOLVE-SMART
    • 23. Januar 2023 um 19:55

    Ehrlich gesagt sehe ich für ein AutoIt-Buch keine Zukunft Peter S. Taler. Dafür gibt es einfach bereits zu viele Tutorials in Form von Videos (auf Youtube oder Udemy) oder Tutorials/How-to's auf irgendwelchen Blog-Seiten sowie eben die beiden Foren (deutsch, englisch) und deren Wiki-Einträge, welche eher genutzt werden als ein Buch fürchte ich.

    Bin leider der Auffassung das zu wenige sich noch mit Büchern zum Thema Programmierung auseinander setzen. Zumindest nicht für diesen zum Großteil semi-professionellen Bereich hier. Ich sehe schon den Vorteil und Mehrwert, doch wie bereits von Gun-Food erwähnt, ist der Anteil derer die mitwirken würden, wahrscheinlich einfach zu klein 😔 .

    Schon allein der Fakt das Tweaky diesen Thread hier am 31. Dez. 2022 eröffnet hat und sich bisher nur sechs verschiedene Leute zu diesem Thema überhaupt geäußert haben, sich bisher nur water dazu bereit erklärt hat, eine Übersetzung vorzunehmen, macht doch leider deutlich wie gering das Interesse oder der Bedarf bei den Nutzern ist. Ein weiterer Fakt ist der Rückgang an Helfenden über die Jahre und die Versionen von AutoIt, siehe post #17.

    Zitat von Gun-Food

    [...] Generell bin ich nicht dagegen und ich richte gern eine entsprechende Seite ein, wenn sich eine große Anzahl an entsprechender Meldungen nicht nur in der Benutzung sondern auch in der Pflege des Wikis wiederfindet. [...]

    Was bedeutet es denn für dich Rene, ein Wiki einzurichten? Sowohl monetär als auch zeitlich? Viel Aufwand? Was hälst du von der Idee ein GitHub Wiki ggf. zu nutzen, welches du public schaltest (siehe post #41)? Dein Projekt/Repo in dem die Hilfe liegt könnte man ja gleich nehmen? Hier im Forum würde es mir persönlich sogar besser gefallen (Wiki), aber wenn es den Aufwand nicht wert sein sollte, dann ist der einfache Weg auf GitHub vielleicht eine Option?


    Danke das du dich als Betreiber der Seite/des Forums, zu Wort gemeldet hast 🤝 .
    Weiterhin alles Gute!

    Zitat von Peter S. Taler

    [...] So Seite 1 unseres Autoit Buches ist schon fertig - wenn Ihr wollt? [...]

    Leider hat sich ein Tippfehler im PDF eingeschlichen Peter S. Taler "ERTELLT" anstatt "ERSTELLT".

    Viele Grüße
    Sven

  • Webdriver xPath iFrames usw.

    • SOLVE-SMART
    • 23. Januar 2023 um 19:25

    Hi Windi, hi gmmg,

    ich glaube wir reden zwar vom Gleichen, jedoch mit einer unterschiedlichen Idee dahinter 😅 .

    Punkt (1)

    Zitat von Windi

    [...] Damals hatte mir Dan, vom englischen Forum geantwortet.

    Von ihm habe ich auch die Fehlerabfrage übernommen. [...]

    Zitat von gmmg

    [...] Prinzipiell mache ich das auch immer so, wie oben angegeben.

    AutoIt
    $sElement = _WD_FindElement($sSession, $_WD_LOCATOR_ByXPath, "/html/body/div[1]/aside[1]/div[2]/div/div[2]/div/div/form/button")
    ;_WD_HighlightElement($sSession, $sElement, 3)
    
    If @error = $_WD_ERROR_Success Then
    _WD_ElementAction($sSession, $sElement, 'click')
    Sleep(500)
    
    ;oder so
    $sElement_login_btn = _WD_FindElement($sSession, $_WD_LOCATOR_ByXPath, '//*[@id="btnLogin"]')

    [...] Gruß gmmg

    Beides okay, in Ordnung und richtig 👍 . Allerdings ist eure Herangehensweise, wenn ich das richtig bewerte diese, dass ihr nur wenn kein Fehler auftritt den nächsten Schritt tun wollt. Also bei @error = $_ED_ERROR_Success dann in die nächste Aktion geht.

    Mein Hinweis bezog sich darauf, dass ich genau andersherum auswerten möchte und beim Auftritt von einem Fehler aus dem Programm aussteigen möchte (oder einfach nur eine MsgBox() oder einen Hinweis auf der Konsole ConsoleWrite() ausgeben möchte), aber eben nicht weiter im Kontext machen möchte. Vereinfacht gesagt vertausche ich die if-else Bedingungen, mehr nicht (IF "Fehler", DANN Return ELSE "weiter im Kontext"). Dies entspricht dem "REP (return early pattern)". Ist jedoch nicht weiter wichtig (dient aber der Erklärung).

    gmmg macht dies sicher richtig und du auch Werner, allerdings in dem konkreten Beispiel deines Skriptes, macht es keinen Sinn meiner Meinung nach. Du weißt das es "irgendwo" instabil ist und eine Aktion nicht korrekt ausgeführt wird, weißt jedoch auf Grund des Logs in der Konsole auch nicht genau welche Stelle es ist. Daher die Variante mit "sobald fehlgeschlagen, aussteigen, den letzten Log Eintrag anschauen und "aha, dort ist es", Ende, finito 😅 .

    Ich denke ich kann morgen das Skript und die Abhängigkeiten zur Verfügung stellen Werner, dann könnt ihr sehr gern nochmal etwas dazu sagen: ob gut oder nicht, bin absolut offen für Verbesserungen 😇 .


    Punkt (2)

    Zitat von Windi

    [...] Dan schrieb dass es an den iFrames hängt.

    Bei meine Orte z. B. [...]

    Ja, konkret ist die Seite in der Automatisierung etwas instabil, weil sie mehrerer iframes einbindet und mit _WD_FrameEnter() und _WD_FrameLeave() gearbeitet werden muss.

    Zitat von Windi

    [...] Weder ChroPath noch SelectorsHub findet da was vernünftiges.

    Hab dann solange rumprobiert bis ich auf den xPath kam.

    Aber wie du schon geschrieben hast, es läuft nicht stabil. [...]

    Des Weiteren nutzt die Webseite Animationen, mit denen der WebDriver nicht immer ohne Zutun umgehen kann. Dies erzeugt das Zeitverhaltenproblem. Nun kann man dies durch genügend Wartezeiten (keine eigenen Sleeps Sleep() sondern über _WaitFor() bzw. _WD_WaitElement()) beheben und in Kauf nehmen, dass das Skript nicht gerade das Schnellste ist (so löse ich das übrigens auch bei deinem Skript/deinem Fall Windi) oder man macht es ganz genau und robust in dem man mit JavaScript Events arbeitet und wirklich wartet bis eine gewissen Animation abgeschlossen ist. Diese Variante ist deutlich aufwändiger und zumindest für mich, nur im beruflichen Kontext relevant.

    Naja, Verbesserungspotenzial gibt es immer 😅 . Melde mich morgen wieder.

    Viele Grüße
    Sven

Spenden

Jeder Euro hilft uns, Euch zu helfen.

Download

AutoIt Tutorial
AutoIt Buch
Onlinehilfe
AutoIt Entwickler
  1. Datenschutzerklärung
  2. Impressum
  3. Shoutbox-Archiv
Community-Software: WoltLab Suite™