nilbo91
Goto Top

Wert aus Quelltext einer HP lesen

Hallo zusammen!
Wünsche erstmal ein frohes neues Jahr.

Kurze Infos zu mir da ich neu in diesem Forum bin:
Frank, 26 Jahre, komme aus Nürnberg, arbeite in München als Consultant für BMW und habe eingentlich nichts mit Programmierung oder Ähnlichem am Hut.
Beschäftige mich seit Anfang meines Weihnachtsurlaubs mit der Batchprogrammierung. Habe zuvor im Techniker ein Jahr mit C# arbeiten müssen.
Mein Ziel sind einfache Arbeitserleichterungen für den beruflichen oder privaten Alltag.

Ich möchte ein Batch erstellen der eine Hompage runterläd, daraus einen Wert ausliest und diesen in einer .txt speichert damit ich diese dann in Excel importieren kann.
Der .txt import zu excel war kein Problem.
Wenn ich die Hompage händisch in Firefox öffne und "speichern unter" txt wähle klappt das auslesen der Werte wunderbar.
Hierfür nutze ich folgenden Code:

for /f %%i in ('Find /n "SUCHBEGRIFF" LINK') do Set LineNo=%%i  
set LineNo=%LineNo:~1,4%
set /a LineNo = %LineNo%+7
set "line="  
set /a LineNo-=1
for /f %%a in ('more/e +%LineNo% ^< LINK') do (  
  if not defined line set "line=%%a"  
)
set line=%line:~0,7%
set euro=%line%

Jetzt möchte ich das runterladen automatisieren und habe dazu ein VBScript gefunden und ein wenig auf meine Anforderungen abgeändert.
Es funktioniert auch einwandfrei, jedoch gibt es den Quelltext der HP aus und den bekomme ich mit meinem bisherigen Code nicht verabeitet.
Egal was ich probiere um an die Werte zu kommen, es kommt immer nur ein Kauderwelsch dabei raus...

Ich hoffe ihr könnt mir helfen.

Grüße Frank

Content-ID: 359774

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

Ausgedruckt am: 25.11.2024 um 01:11 Uhr

StefanKittel
StefanKittel 03.01.2018 um 14:56:52 Uhr
Goto Top
Hallo,

probiere es mal mit wget.
Damit kann man prima webseiten runterladen und den Inhalt speichern.

Stefan
Nilbo91
Nilbo91 03.01.2018 um 15:50:48 Uhr
Goto Top
Da ich das Script auch auf anderen PCs nutzen möchte würde ich es gerne nur mit den Bordmitteln von WIndows realisieren.
colinardo
colinardo 03.01.2018 aktualisiert um 17:12:31 Uhr
Goto Top
Servus Frank,
also wenn es dir daraum geht den reinen Text der Webseite ohne HTML-Tags zu bekommen da gibt es so einige Möglichkeiten, hier ein paar davon:

Direkt in Excel mit VBA-Makro
Sub GetWebSitePlainText()
    Const URL = "https://administrator.de"  
    dim objhttp as object, dom as object
    Set objhttp = CreateObject("Microsoft.XMLHTTP")  
    Set dom = CreateObject("htmlfile")  
    With objhttp
        .Open "GET", URL, False  
        .send
        If .Status = 200 Then
            dom.write .responseText
            MsgBox dom.body.innerText
        End If
    End With
End Sub
Oder als Powershell Einzeiler:
(iwr -Uri 'https://administrator.de').ParsedHtml.body.innerText  
usw. face-smile

Aber normalerweise ist auch das Extrahieren aus dem HTML-Code mit etwas Regular Expressions kein wirkliches Problem, wenn du diesen Ausschnitt den du suchst hier postest kann ich dir auch gerne den genauen Weg zu deinem gewünschten String hier posten.

Grüße Uwe
Nilbo91
Nilbo91 03.01.2018 um 18:10:51 Uhr
Goto Top
Schon mal vielen Dank im vorraus Uwe!

Mit Powershell habe ich mich noch nicht befasst.
Schön wäre es natürlich den Powersehll Einzeiler in einer Batch verarbeiten zu können.
Werde mich mal damit beschäftigen nachdem ich das Makro ausprobiert habe.

Hier ein ausschnitt des Textes
.
<div class="snapshot-header snapshot">  
    <div class="quote-data">  
      <span class="time">Kurs vom&nbsp;03.01.2018&nbsp;17:32</span><br/>  
      <strong class="price price-minus">  

            1.316,10</strong>
            <span class="currency">USD</span>  
            <br/>

        <span class="minus">-0,31%</span> | -4,13</div>  

    <div class="security-data">  

Es geht um den aktuellen Kurs von Gold. (1.316,10 in Zeile 6)
Mir ist aufgefallen, dass der Code hier im Post scheinbar anders verarbeitet wird. In meiner txt (bei einer html ebenso) gibt es keine Zeilenumbrüche. Da wird nur durch unzählige Leerzeichen getrennt und es sieht aus wie ein einziger Fließtext.

Wie du sicherlich oben gesehen hast habe ich mir die Zeilennummer ausgeben lassen in dem mein Suchbegriff gefunden wurde. Dann habe ich (bisher) nur die zusätzlichen Zeilen zählen und aufaddieren müssen und konnte dann per Stringmanipulation den Wert isolieren. Hier klappt das aber irgendwie nicht....

Ich wäre über eine Lösung oder einen Tip von dir sehr dankbar^^

Grüße Frank
colinardo
Lösung colinardo 03.01.2018 aktualisiert um 19:57:19 Uhr
Goto Top
Kein Problem, schick mir einfach mal den Link zur betreffenden Website dann habe ich den besseren Zusammenhang und extrahiere dir den Wert direkt per Regex, denn das mit den Zeilen ist wie du siehst mies und unzuverlässig.
Hier ist mal ein einfaches Beispiel für den Goldpreis von "http://www.goldpreis.de", das du direkt in der CMD ausführen kannst (Bei Platzierung in einer Batch ist das % Zeichen zu verdoppeln).
powershell -Executionpolicy Bypass -NoProfile -Command "(iwr -Uri 'https://www.goldpreis.de/').ParsedHtml.getElementsByClassName('au_gold_usd_o') | %{$_.innerText.Trim()}"  
Nilbo91
Nilbo91 04.01.2018 aktualisiert um 09:35:31 Uhr
Goto Top
Ich danke dir für die Hilfe!
Bitte mach dir aber nicht die Mühe den Wert per Regex zu isolieren.
Habe gesehen, dass du das selbst gebaut hast und gleich eine ausfühliche Anleitung mitgeliefert hast.
Wie ich oben schon geschrieben habe möchte ich die Batch auch auf anderen Rechnern nutzen und möchte/kann nicht überall die nötigen zusatzprogramme installieren.

Die Lösung mit Powershell gefällt mir super.
Wenig Text, keine zusätzlichen Datein und scheinbar auch recht zügig. (Habe momentan lausiges Internet)

Hier der Link.

1

Werde mich jetzt mal an dein Goldpreis Beispiel machen. Will ja schließlich auch verstehen was da passiert^^
colinardo
Lösung colinardo 04.01.2018 aktualisiert um 10:19:24 Uhr
Goto Top
Gut, für die Consors-Seite brauchst du hier ausnahmsweise diesmal nur die URL und den Klassennamen entsprechend austauschen da es auch hier nur ein Element mit dem jeweiligen Klassennamen auf der Seite gibt:
powershell -Executionpolicy Bypass -NoProfile -Command "(iwr -Uri 'https://www.consorsbank.de/Wertpapierhandel/Snapshot/id1326189').ParsedHtml.getElementsByClassName('price') | %{$_.innerText.Trim()}"  
Will ja schließlich auch verstehen was da passiert
Nun es passiert folgendes:
Die Seite wird mit iwr = Invoke-Webrequest heruntergeladen und in ein Objekt geladen von dem wir die Eigenschaft ParsedHtml abrufen und aus diesem die Methode getElementsByClassName('KLASSENNAME') aufrufen welche die Knoten mit dem entsprechenden Klassennamen ausfiltert. Dann wird per Foreach-Schleife (%{}) die Eigenschaft innerText des Knotens ($_ ist die Pipelinevariable) ausgelesen und eventuelle Leerzeichen am Anfang oder Ende des Strings entfernt.

Hoffe das bringt etwas Licht ins Dunkel. Leider kann ich dir hier keinen Grundkurs Powershell geben, aber vielleicht einen Anreiz sich die Skript-Sprache näher anzuschauen face-wink

Wünsche Dir weiterhin viel Erfolg!
Grüße Uwe
Nilbo91
Nilbo91 04.01.2018 um 15:12:05 Uhr
Goto Top
Ok alles klar. Das getElementsByClassName habe ich verstanden. Die Umleitung der Ausgabe in eine txt hat auch geklappt.

Bei der nächsten HP sieht es aber nun so aus...
          <td class="col-info">BTC<span class="show35">/</span>USD</td>  

          <td class="col-currency">14424.0</td>  
Zeilen 640 - 642

...mit "class=col-currency" schmeißen die auf www.bitfinex.com/stats leider nur so um sich.
Komme also wieder nicht weiter -.-

Leider finde ich auch keine HP die mir die verfügbaren Funktionen in Powershell erklärt. Mit www.batchlog.pytalhost.com/Batch.html konnte ich mir bisher fast alles selber erarbeiten. Gibt es sowas auch für Powershell?

Grüße Frank
colinardo
Lösung colinardo 04.01.2018 aktualisiert um 16:31:31 Uhr
Goto Top
Hallo nochmal,
da gibt es mehrere praktische Ansätze. Entweder man kennt die absolute Position (die man manuell ermitteln kann) und nimmt dann den Index der Auflistung, oder man sucht erst nach dem BTC/USD Knoten und referenziert dann den nächsten Nachbarknoten (nextSibling), was hier bspw. mein Weg wäre:
powershell -ExecutionPolicy ByPass -NoProfile -Command "(iwr -Uri 'https://www.bitfinex.com/stats').ParsedHtml.getElementsByClassName('col-info') | ?{$_.innerText -eq 'BTC/USD'} | select -First 1 | %{$_.nextSibling.innerText.trim()}"  
Leider finde ich auch keine HP die mir die verfügbaren Funktionen in Powershell erklärt.
Das ist auch fast unmöglich, denn Powershell unterstützt das gesamte Arsenal des .NET Frameworks. D.h. alles was du auch in C#, VB.Net etc. machen kannst kannst du auch mit der Powershell erledigen.
In deinem Fall hier kommen noch die Grundlagen des gesamten HTML-DOM-Object hinzu welche Invoke-Webrequest mit der Eigenschaft parsedHtml bereitgestellt werden. Überfordere dich nicht, lerne es Schritt für Schritt, denn sonst verlierst du den Überblick, Quereinstieg schön und gut aber Grundlagen sind hier Pflichtprogramm und natürlich üben, üben, üben.
Hast du einmal den Bogen raus möchtest du Batch nicht mehr sehen, glaubs mir.

Ein guter Anfang für die Powershell Grundlagen:

Powershell Grundlagen- und Praxisvermittlung:


Wenns das dann war, den Beitrag bitte noch auf gelöst setzen, und Lösungen markieren. Merci.

Grüße Uwe
Nilbo91
Nilbo91 05.01.2018 um 16:35:27 Uhr
Goto Top
Vielen Danke für die Hilfe.
Nun klappt alles!

Eine letzte Frage rein zur Optimierung:
Kann man an den ersten Suchauftrag zB. wie in deinem Code oebn BTC/USD noch einen zweiten anhängen?

Auf der HP auf der BTC/USD steht, stehen nämlich noch 2 weitere Werte die ich brauche und jetzt "läd" bzw durchsucht das programm jedes mal die komplette Seite erneut. IOTA/USD und XRP/USD.


Grüße Frank

PS: Danke für die Links. Werde sie mir zeitnah zu Gemüte führen ;)
colinardo
colinardo 05.01.2018 aktualisiert um 16:59:40 Uhr
Goto Top
Mit dem -match Operator und etwas Regular Expressions z.B.
powershell -ExecutionPolicy ByPass -NoProfile -Command "(iwr -Uri 'https://www.bitfinex.com/stats').ParsedHtml.getElementsByClassName('col-info') | ?{$_.innerText -match '^(IOTA/USD|BTC/USD|XRP/USD)$'} | Select -First 3 | %{$_.innerText + ':' + $_.nextSibling.innerText.trim()}"  
Das Select -First 3 hier weil unten auf der Seite die Werte nochmal erscheinen.

Alternativ kann man auch die Werte in einem Array ablegen und dann im Where-Object mit dem -in Operator prüfen ob ein Wert mit dem Array übereinstimmt.

-edit- Tippfehler korrigiert