kime203
Goto Top

Powershell - Webseite auslesen und Abspeichern ein paar Probleme

Hallo alle miteinander,


ich hab die Aufgabe eine Webseite auszulesen um Einsatzdaten der Feuerwehr daraus zu gewinnen. Das habe ich soweit auch schon am laufen. Dazu ist es notwendig mit Cookies zu arbeiten. So schaut das aus.

[System.Uri]$uri="https://demo.demo/"  

$Cookie= New-Object System.Net.Cookie
$Cookie.Name = "demo"  
$Cookie.Value = "demo"  
$Cookie.Domain = $uri.DnsSafeHost

$WebSession = New-Object Microsoft.PowerShell.Commands.WebRequestSession
$WebSession.Cookies.Add($Cookie)
$props= @{ Uri=$uri.AbsoluteUri
WebSession=$Websession}

$data = Invoke-RestMethod @props

$data.Einsatzdata | Format-List -Property EinsatzID,Alarmstufe,Meldebild,Lat,Lng,Nummer1,Plz,Strasse,Ort,Bemerkung,EinsatzErzeugt,Melder,MelderTelefon  > "c:\temp\einsatz.txt"  

das kommt dabei so raus

EinsatzID      : XXX
Alarmstufe     : B2
Meldebild      : Wohnungsbrand
Lat            : 99,999999
Lng            : 99,999999
Nummer1        : 99
Plz            : 9999
Strasse        : XXX
Ort            : XXX
Bemerkung      : XXX
EinsatzErzeugt : 2019-08-21T11:36:56.6284335+02:00
Melder         : Max Mustermann
MelderTelefon  : 000

Soweit so gut jetzt habe ich noch 2 Problem

1. Lat und bei Lng muss ist anstelle des , einen . setzten da die verarbeitende Software das nur so versteht. Das habe ich so versucht
$data.Einsatzdata.Lat -Replace ',', '.'  
das funktioniert auch aber nicht ganz so wie ich das möchte. So wir eine neue Zeile gemacht und nicht die vorhanden geändert.

Bei dem Punkt EinsatzErzeugt müsste das Datum und die Uhrzeit so angezeigt werden 01.01.2019 23:00:00
$zeit = Get-Date -Format "dd/MM/yyyy HH:mm:ss"  
Wie ich das so bekomme habe ich geschafft aber wie ich es ersetze leider auch wieder nicht.

2. Dieser Script sollt immer laufen und die Webseite überprüfen ob eine Veränderung stattgefunden hat. Zu dem Punkt habe ich noch nicht wirklich etwas gefunden. Wenn kein Einsatz ist und ich den Script ausführe wir eine 0 Bit Größe Datei gemacht da die Webseite dann keinen Inhalt hat. Toll wäre es wenn das so ist das keine Datei angelegt wird und dann nach 30 sek erneut angefragt wird ob jetzt eine Änderung ist.

Ich hoffe ich konnte mein Anliegen verdeutlichen und bin über jede Hilfe sehr dankbar. Sollte jemand eine andere Lösung für die Aufgabe haben dann bitte her damit face-smile

LG Alex

Content-Key: 487541

Url: https://administrator.de/contentid/487541

Printed on: April 19, 2024 at 09:04 o'clock

Mitglied: 140777
140777 Aug 22, 2019 updated at 14:19:29 (UTC)
Goto Top
Daten im Format-List Format zu bearbeiten macht man nicht, das ist Humbug! Also direkt die Objekte bearbeiten.
$result = $data.Einsatzdata | select EinsatzID,Alarmstufe,Meldebild,Lat,Lng,Nummer1,Plz,Strasse,Ort,Bemerkung,EinsatzErzeugt,Melder,MelderTelefon
$result.Lat = $result.Lat.toString().replace(',','.')  
$result.Lng = $result.Lng.toString().replace(',','.')  
$result.EinsatzErzeugt = Get-Date $result.EinsatzErzeugt.toString() -F "dd/MM/yyyy HH:mm:ss"  
# export als CSV
$result | export-csv "c:\temp\einsatz.csv" -NoType -Delimiter ";" -Encoding UTF8  
# oder als Text
$result | fl * | sc "c:\temp\einsatz.txt"  
Dieser Script sollt immer laufen und die Webseite überprüfen ob eine Veränderung stattgefunden hat
Aufgabenplanung.
Wenn kein Einsatz ist und ich den Script ausführe wir eine 0 Bit Größe Datei gemacht da die Webseite dann keinen Inhalt hat.
Prüfe halt einfach die Variable in Zeile 13 des Invoke-Restmethod auf Inhalt mit nem simplen if(){ } ...
Was die an Inhalt hat können wir hier ja nicht testen mangels URL. Lass dir mit Get-Member die zurückgegebenen Werte anzeigen dann kannst du entsprechend mit if Abfrage verzweigen.
Member: kime203
kime203 Aug 22, 2019 at 14:15:18 (UTC)
Goto Top
Ok also das funktioniert so leider mal nicht es kommt dieser Fehler
Fehler beim Aufrufen der Methode, da [System.Decimal] keine Methode mit dem Namen "replace" enthält.  
In C:\Users\global\Einsatz_Monitor\einsatz1.ps1:23 Zeichen:1
+ $result.Lat.replace(',','.')  
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) , RuntimeException
    + FullyQualifiedErrorId : MethodNotFound

und auch sonst wird nichts ausgegeben.

Aufgabenplanung das er alle 30 sek den Script laufen lassen soll? Ok dachte vielleicht gibt es da direkt etwas.

Ok if(){ } ... leider bin ich nicht sehr vertraut mit PowerShell und kann jetzt nicht ganz verstehen wie das helfen soll kann.

Danke für deine Antwort vielleicht finden wir ja noch eine Lösung.
Mitglied: 140777
Solution 140777 Aug 22, 2019 updated at 14:45:37 (UTC)
Goto Top
Oben korrigiert, habe hier ja die deine Originaldaten nicht sorry! Wenn du die URL posten würdest könnte man es direkt fertig machen.

Aufgabenplanung das er alle 30 sek den Script laufen lassen soll? Ok dachte vielleicht gibt es da direkt etwas.
Kannst auch eine while(){} DauerSchleife laufen lassen. Jacke wie Hose.


Ok if(){ } ... leider bin ich nicht sehr vertraut mit PowerShell und kann jetzt nicht ganz verstehen wie das helfen soll kann.
Naja, nachschlagen wäre mal die erste Methode ... https://www.windowspro.de/script/if-else-switch-bedingte-anweisungen-pow ...

z.B.
if ($data){
    $result = $data.Einsatzdata | select EinsatzID,Alarmstufe,Meldebild,Lat,Lng,Nummer1,Plz,Strasse,Ort,Bemerkung,EinsatzErzeugt,Melder,MelderTelefon
    $result.Lat = $result.Lat.toString().replace(',','.')  
    $result.Lng = $result.Lng.toString().replace(',','.')  
    $result.EinsatzErzeugt = Get-Date $result.EinsatzErzeugt.toString() -F "dd/MM/yyyy HH:mm:ss"  
    # export als CSV
    $result | export-csv "c:\temp\einsatz.csv" -NoType -Delimiter ";" -Encoding UTF8  
    # oder als Text
    $result | fl * | out-string | sc "c:\temp\einsatz.txt"  
}
Aber ich weiß ja nicht welchen Inhalt dein $data hat wenn die Webseite nichts liefert deswegen kann ich hier nur mutmaßen. Deswegen der Hinweis lass dir den Inhalt bzw. die Member von $data ausgeben
$data | Get-Member
Wenn dann die Fehlermeldung kommt das es keine Member von einem null Objekt gibt dann funktioniert obige Abfrage, ansonsten ist die Bedingung anzupassen, je nachdem was Invoke-RestMethod liefert wenn die Webseite keinen Inhalt zurückgibt.
Member: kime203
kime203 Aug 22, 2019 at 14:39:16 (UTC)
Goto Top
Danke für deine Hilfe selbst wenn ich dir die URL gebe funktioniert das nicht da es über einen Token gesichert ist daher habe ich das raus genommen.

while(){} hört sich gut an (ich lese durch aus vorher was das ist aber mir fehlt da leider noch der Durchblick dafür sorry)

Dein Script hat mir das jetzt ausgeben
Microsoft.PowerShell.Commands.Internal.Format.FormatStartData
Microsoft.PowerShell.Commands.Internal.Format.GroupStartData
Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData
Microsoft.PowerShell.Commands.Internal.Format.GroupEndData
Microsoft.PowerShell.Commands.Internal.Format.FormatEndData

$data ist ein json Datei mit diesem Inhalt der bei einem Aktiven Einsatz dort zu finden ist. Wenn keine Einsatz Aktiv ist ist dort nichts.
EinsatzID      : XXX
Alarmstufe     : B2
Meldebild      : Wohnungsbrand
Lat            : 99,999999
Lng            : 99,999999
Nummer1        : 99
Plz            : 9999
Strasse        : XXX
Ort            : XXX
Bemerkung      : XXX
EinsatzErzeugt : 2019-08-21T11:36:56.6284335+02:00
Melder         : Max Mustermann
MelderTelefon  : 000

Kannst du mir das mit dem Get-Member genauer erklären das hab ich auch schon versucht aber da ist nix dabei raus gekommen so recht.
Mitglied: 140777
140777 Aug 22, 2019 updated at 14:50:04 (UTC)
Goto Top
Was gibt ein
$data.GetType()
zurück? Es gibt hier nämlich einige Varianten wie Daten zurückgegeben werden können, Der JSON String wird normalerweise von Invoke-Restmethod direkt zu einem Object oder einem Array konvertiert und je nachdem wie das JSON formatiert ist ist dies eben unterschiedlich aufgebaut und muss unterschiedlich behandelt werden! Wenn das nämlich ein Array ist muss das Ansprechen z.B. so geschehen $data.EinsatzID
Member: kime203
kime203 Aug 22, 2019 at 14:49:38 (UTC)
Goto Top
IsPublic IsSerial Name                                     BaseType                                                                                                                           
-------- -------- ----                                     --------                                                                                                                           
True     False    PSCustomObject                           System.Object                                                                                                                      
Mitglied: 140777
Solution 140777 Aug 22, 2019 updated at 14:53:49 (UTC)
Goto Top
Ok in dem Fall sollte ein zwischengeschaltetes Out-string helfen
$result | fl * | out-string | sc "c:\temp\einsatz.txt"  
Member: kime203
kime203 Aug 22, 2019 at 15:08:44 (UTC)
Goto Top
Ok das funktioniert jetzt genau so wie gewünscht danke.

Kannst du mir mit dem while(){} noch helfen ;)
Mitglied: 140777
Solution 140777 Aug 22, 2019 updated at 16:31:17 (UTC)
Goto Top
Kannst ja noch ein Detail vorher noch auf Unterschied zum letzten Request checken und nur dann in die Datei ausgeben (ergänzt).
# rest ... von vor Zeile 13
$lastID = 0
while($true){
    $data = Invoke-RestMethod @props
    if ($data){
        $result = $data.Einsatzdata | select EinsatzID,Alarmstufe,Meldebild,Lat,Lng,Nummer1,Plz,Strasse,Ort,Bemerkung,EinsatzErzeugt,Melder,MelderTelefon
        if ($result.EinsatzID -ne $lastID){
            $result.Lat = $result.Lat.toString().replace(',','.')  
            $result.Lng = $result.Lng.toString().replace(',','.')  
            $result.EinsatzErzeugt = Get-Date $result.EinsatzErzeugt.toString() -F "dd/MM/yyyy HH:mm:ss"  
            $result | fl * | out-file "c:\temp\einsatz.txt"  
            $lastID = $result.EinsatzID
        }
    }
    sleep -Seconds 5
}
Member: kime203
kime203 Aug 22, 2019 at 15:16:33 (UTC)
Goto Top
Danke Danke Danke genau so jetzt verstehe ich auch besser wie das zusammenspiele lauft.
Member: kime203
kime203 Aug 22, 2019 at 15:37:18 (UTC)
Goto Top
Ok doch nicht ganz ich hab das mit while verstanden und mit true ist das ein loob der endlos läuft nur eine abfrage ob hier sich etwas geändert hat. Du hast das vorher schon angesprochen mit

Prüfe halt einfach die Variable in Zeile 13 des Invoke-Restmethod auf Inhalt mit nem simplen if(){ } ...
Was die an Inhalt hat können wir hier ja nicht testen mangels URL. Lass dir mit Get-Member die zurückgegebenen Werte anzeigen dann kannst du entsprechend mit if Abfrage verzweigen.

Wo baut man das jetzt noch dazu ein? Wenn ich zB schauen will ob sich EinsatzID geändert hat und wenn die nicht vorhanden ist schreibe auch keine Datei.
Mitglied: 140777
140777 Aug 22, 2019 updated at 15:53:59 (UTC)
Goto Top
Wenn ich zB schauen will ob sich EinsatzID geändert hat und wenn die nicht vorhanden ist schreibe auch keine Datei.
Ist oben eingesetzt. Das ganze speichert die letzte EinsatzID beim schreiben der Textdatei in der Variablen $lastID. Wenn bei einem erneuten Abruf der Seite sich die aktuelle EinsatzID von der letzten unterscheidet dann wird die Textdatei neu geschrieben ansonsten nicht. Wäre ja Blödsinn alle 5 Sekunden die Datei neu zu schreiben obwohl sich nichts auf der Seite geändert hat face-wink.
Ich gehen hier natürlich davon aus das die EinsatzID bei jedem neuen Einsatz anders ist als der vorherige. Ansonsten ändere die Eigenschaft einfach auf die die du dazu benutzen willst.
Member: kime203
kime203 Aug 22, 2019 at 15:58:28 (UTC)
Goto Top
Ja das ist richtig jeder Einsatz hat eine neue ID. Das klapp. Er schreibt zwar einmal noch eine leere Datei aber das wir wohl so sein. $lastID = "" was bewirkt der da jetzt nur damit ich es auch verstehe.
Mitglied: 140777
140777 Aug 22, 2019 updated at 16:02:33 (UTC)
Goto Top
Zitat von @kime203:
$lastID = "" was bewirkt der da jetzt nur damit ich es auch verstehe.
Das ist einfach nur das initiales Deklarieren der Variablen ohne Inhalt, hinterher enthält die ja jeweils immer die letzte ID.
Auch hier hilft wieder nachschlagen: Variablen in PowerShell: Namen, Werte, Datentypen
Member: kime203
kime203 Aug 22, 2019 at 16:02:23 (UTC)
Goto Top
Ja alle deine Links habe ich die letzten Tage schon mal gelesen face-smile nur das merken ist noch so eine Sache
Mitglied: 140777
140777 Aug 22, 2019 updated at 16:04:47 (UTC)
Goto Top
Zitat von @kime203:
nur das merken ist noch so eine Sache
Da hilft nur üben üben und nochmal üben, wie überall face-smile. Selbst Übungsaufgaben stellen und so lange dran bleiben bis es klappt auch mal ohne Forum, nur so bleibt es wirklich hängen.

Viel Erfolg weiterhin.

Ciao.
Member: kime203
kime203 Aug 22, 2019 at 16:14:58 (UTC)
Goto Top
Danke noch mal ich hab jetzt noch das geändert
if ($result.EinsatzID -gt $lastID)
mit -gt anstelle von -ne wird nur eine Datei erstellt wenn auch etwas drin steht.

Auf jedenfalls noch mal ein Größe Dankeschön.
Mitglied: 140777
140777 Aug 22, 2019 updated at 16:55:28 (UTC)
Goto Top
In dem Fall ist die EinsatzID vom Typ Integer bzw. eine Zahl, da reicht es wenn du in die Deklaration von $lastID statt einem String eine 0 schreibst, dann geht es ebenfalls problemlos mit -ne, aber wenn die ID sowieso immer größer wird geht das natürlich auch mit -gt face-wink.
Aber auch wenn der Inhalt von $lastID ein String wäre wäre der Vergleich einer Zahl mit einem leerem String $true muss also auch gehen, kannst du ganz einfach selbst testen
10 -ne ""  
Ergibt
$true
If Bedingung wird also ausgeführt.

mit -gt anstelle von -ne wird nur eine Datei erstellt wenn auch etwas drin steht.
Achso so die Website gibt also in jedem Fall immer ein Object zurück, nur eben alle Properties ohne Werte? In dem Fall ist die eine IF-Bedingung die $data checkt nicht passend.
In dem Fall musst du die Zeile
if ($data){
so schreiben
if ($data.EinsatzData.EinsatzID -gt 0){
Dann ist das damit schon abgefackelt. Ich war davon ausgegangen das die Webseite überhaupt nichts zurückgibt ...