c20082005
Goto Top

Powershell - bestimmten Wert aus Webseite auslesen

Hallo zusammen,

ich möchte aus der Webseite meines Raspberrys (Volumio läuft dort) einen bestimmten Wert auslesen.
Wenn ich die Webseite mit Chrome öffne und abspeichere, kann ich den Wert, der mich interessiert (der Wert "0:36" nach "ng-binding ng-scope"), finden und auslesen.

<div class="bigText"><!-- ngIf: trackManager.playerService.state.trackType !== 'webradio' && trackManager.playerService.state.service !== 'analogin' --><span ng-if="trackManager.playerService.state.trackType !== 'webradio' &amp;&amp; trackManager.playerService.state.service !== 'analogin'" class="ng-binding ng-scope">0:36</span><!-- end ngIf: trackManager.playerService.state.trackType !== 'webradio' && trackManager.playerService.state.service !== 'analogin' --><!-- ngIf: trackManager.playerService.state.trackType === 'webradio' --></div> 

Auslesen mit Powershell:
$iwr=Invoke-WebRequest ("http://volumio/playback")  
Lese ich die Seite mit Invoke Webrequest aus, habe ich das Problem, dass ich diese Information nicht finde.
Wo ist diese Zeichenfolge "versteckt"?

Gibt es in Powershell eine Möglichkeit, den Inhalt von Invoke Webrequest zu durchsuchen?
Kann ich ´z.B. nach "ng-binding ng-scope" suchen und Powershell gibt mir die Stelle zurück, in der der Suchstring steht?

Kann ich (wie Chrome) den kompletten Inhalt der Webseite abspeichern, so dass ich den Quellcode durchsuchen kann?

Ich würde mich über eine Lösung sehr freuen!

Gruß

Klaus

Content-ID: 400367

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

Ausgedruckt am: 22.11.2024 um 14:11 Uhr

colinardo
colinardo 03.02.2019 aktualisiert um 17:36:54 Uhr
Goto Top
Servus Klaus,
kein Problem, ohne jetzt den weiteren Inhalt zu kennen und ob die Seite dynamisch per JavaScript generiert wird( in den Fall geht das unten stehende nicht), select des ersten "SPAN" Elements mit Klassen "ng-binding ng-scope"
back-to-topVariante über "AllElements"-Eigenschaft
$req = iwr 'http://volumio/playback'  
$content = $req.AllElements | ?{$_.tagname -eq 'SPAN' -and $_.class -eq 'ng-binding ng-scope'} | select -First 1 -Expand InnerText  
$content

Es gibt noch weitere Varianten, z.B. über die Eigenschaft ParsedHtml mit der man ebenfalls die Elemente der Seite objektorientiert durchwandern kann.
back-to-topVariante über "ParsedHtml"-Eigenschaft
$req = iwr 'http://volumio/playback'  
$content = $req.ParsedHtml.getElementsByTagName('SPAN') | ?{$_.className  -eq 'ng-binding ng-scope'} | select -First 1 -Expand innerText  
$content
Oder auch mit Regex und der Eigenschaft content des WebRequest in der man den HTML Quellcode bekommt.
back-to-topVariante Regular Expressions über die "Content"-Eigenschaft
$req = iwr 'http://volumio/playback'  
$content = [regex]::match($req.Content,'(?is)(?<=<span.*?class="ng-binding ng-scope">)[^<]*').Value  
$content
Such dir was aus face-smile. Schema sollte ja jetzt durch die Beispiele klar sein.

Grüße Uwe
c20082005
c20082005 03.02.2019 aktualisiert um 18:04:26 Uhr
Goto Top
Hallo Uwe,

danke für Deine Antwort.
Leider bringen diese Befehle nicht das Gewünschte - es wird nichts gefunden.

Das, was da von Invoke-webrequest zurückkommt, ist ja gewaltig.
Da gibt es AllElements, Content, ParsedHtml uvm.
Hinter diesen gibt es dann wieder 1000 Informationen auszulesen.
Ich habe schon einiges durchgesehen - ohne Erfolg.

Gibt es eine Möglichkeit, das Invoke-Webrequest "komplett" abzuspeichern (und dann aus dem Wust das Gewünschte zu suchen)?

Wenn ich mit Chrome den Quellcode abspeichere, kann ich den String suchen und finden.
Gibt es eine Möglichkeit, den Quellcode automatisch in Powershell einzulesen und dann zu suchen?
Ich habe das schon so probiert:
Invoke-WebRequest ("http://volumio/playback") -outfile "f:\text.txt"  
Dann speichert er aber nur einen kleinen Teil ab (Größe: 3kB / Größe der HTML-Datei von Chrome: 24kB).

Gruß

Klaus
colinardo
colinardo 03.02.2019, aktualisiert am 04.02.2019 um 12:56:23 Uhr
Goto Top
Dann wird deine Seite dynamisch mit JavaScript aufgebaut. Wie oben geschrieben bringt dir der WebRequest mit Invoke-WebRequest in dem Fall nichts, weil hier kein JavaScript Interpreter arbeitet sondern nur statischer Content geladen wird.
Indem Fall musst du ein Objekt nehmen das das Clientside JavaScript auswertet. Das kannst du z.B. mit dem InternetExplorer.Application COM-Object machen. Such mal im Forum nach meinen Beiträgen dazu, dazu habe ich schon etliche Skripte hier gepostet.
Wie z.B. hier
Gmail Login-Script -Powershell- hat Probleme mit Methoden
hier
Finaler Content aus scriptgenerierter Webseite auslesen
und auch hier
Powershell - Aufruf von HTML Verknüpfungen mit Fensteranpassung und automatische Eingabe des Passwords möglich?
usw.

# Neuen IE-Prozess erzeugen
$i = New-Object -Com InternetExplorer.Application
# Fenster unsichtbar machen
$i.Visible = $false
# Webseite aufrufen
$i.Navigate("http://volumio/playback")  
while($i.Busy){sleep .3}
# Zusätzlichen sleep einbauen damit dynmaischer Content nachgeladen werden kann
sleep 2
# irgendein DOM-Object auslesen, im Beispiel den reinen Body als HTML ausgeben
# $i.document.Body.innerHTML
# oder nach Tags suchen und deren Inhalt ausgeben
$i.document.getElementsByTagName('SPAN') | ?{$_.className -eq 'ng-binding ng-scope'} | %{$_.innerHTML}  
# Browser beenden
$i.Quit()
# COM ressourcen freigeben
[System.Runtime.InteropServices.Marshal]::ReleaseComObject($i) | out-null
c20082005
c20082005 10.02.2019 um 09:13:22 Uhr
Goto Top
Leider sagt Volumio "Nein" zum Internet Explorer ("You are using an outdated browser.").

Ich habe dann versucht, andere Browser per Kommandozeile dazu zu bringen, die Seite abzuspeichern.
Das ist ja ein mühsames Geschäft!
Unter Chrome habe ich es geschafft, die Seite im PDF-Format zu speichern

chrome --headless --print-to-pdf="d:\Seite.pdf" http://volumio  

Das bringt natürlich nichts, weil man das PDF nicht nach diesem String durchsuchen kann.

Chrome / Firefox oder Opera - all diese Browser habe ich mit Kommandozeile-Befehlen beschäftigt, aber es nicht hinbekommen, dass die diese Seite abspeichern (und ich dann die Datei mit Powershell durchsuchen kann).

Schade - ich gebe auf und bedanke mich trotzdem für Deine Mühe.

Gruß

Klaus
colinardo
colinardo 10.02.2019 aktualisiert um 09:56:13 Uhr
Goto Top
Leider sagt Volumio "Nein" zum Internet Explorer ("You are using an outdated browser.").
User Agents lassen sich auch per API faken.
Alternative zum IE ist die Browser API vom FF GeckoFX damit ginge das auch problemlos.
Das bringt natürlich nichts, weil man das PDF nicht nach diesem String durchsuchen kann.
Kannst du schon (iTextSharp), aber das wäre vollkommen ineffizient, also Finger weg.

ich gebe auf
Schade ist eigentlich ein Kinderspiel.

Gegen Aufwandsentschädigung teste ich dir das gerne an der Seite in einer VM.

p.s. Noch effizienter wäre es wenn man gleich ein Skript in die Seite einbaut (Plugin) welches die gewünschten Daten direkt irgendwo hin schreibt, da da im Hintergrund vermutlich PHP und JavaScript arbeiten wäre das auch nicht weiter schwer.
colinardo
Lösung colinardo 10.02.2019 aktualisiert um 16:48:44 Uhr
Goto Top
Habe mit das Volumio-Projekt gerade mal angesehen.
Nutze einfach die REST API
https://volumio.github.io/docs/API/REST_API.html
Über die URL
<IPVOLUMIO>/api/v1/getstate
bekommst du mit der Eigenschaft Seek genau das was du möchtest, die aktuelle Playposition per JSON frei Haus geliefert face-wink

Volumio2 kommuniziert dagegen über WebSockets, damit lässt sich das ganze ebenfalls direkt abfragen:
https://github.com/volumio/Volumio2/wiki/WebSockets-API-Reference
c20082005
c20082005 11.02.2019 um 18:54:48 Uhr
Goto Top
Vielen Dank!

Jetzt habe ich es ja doch hinbekommen!
Der Verweis auf die REST API hat mich gerettet.

Ist ja auch genial, dass man Volumio damit steuern kann.
So lässt sich damit der Kasten in Pause versetzen:
$Url="http://volumio/api/v1/commands/?cmd=pause"  
$iwr=Invoke-WebRequest ($Url)

Hier meinen Code für die Nachwelt

Url="http://volumio/api/v1/getstate"  
$iwr=Invoke-WebRequest ($Url)

$Volumio_Suchbegriff='"seek":'  
$Volumio_Stelle_im_String=$iwr.Content.IndexOf($Volumio_Suchbegriff)
# Bis zum Wert abschneiden
$Volumio_TEMP=$iwr.Content.Substring($Stelle_im_String+$Volumio_Suchbegriff.Length)
# Das Zeichen nach dem Wert finden
$Volumio_Stelle_im_String=$Volumio_TEMP.IndexOf(',')  
# Wert zuweisen
$script:Volumio_Playposition_aktuell=$Volumio_TEMP.Substring(0,$Volumio_Stelle_im_String)

Danke nochmals und Gruß

Klaus
colinardo
Lösung colinardo 11.02.2019 aktualisiert um 19:00:45 Uhr
Goto Top
Hier meinen Code für die Nachwelt
Das geht viel einfacher, schau dir mal Invoke-Restmethod an face-wink. Das erstellt aus dem zurückgelieferten JSON direkt ein Objekt.

Kanns jetzt nicht testen aber das sollte das ganze abkürzen
(irm 'http://volumio/api/v1/getstate').seek  
Ebenfalls für JSON-Strings nützlich ConvertFrom-JSON um JSON in ein Objekt zu wandeln.

Grüße Uwe
c20082005
c20082005 11.02.2019 um 19:11:26 Uhr
Goto Top
Spitze!
Danke!

        $Url="http://volumio/api/v1/getstate"  
        $iwr=Invoke-WebRequest ($Url)
        $script:Volumio_Playposition_aktuell=(Invoke-RestMethod $Url).seek