NEWS
[Gelöst] Werte von Clever Tanken
-
Huhu,
ich würde gerne von Tankstellen hier in der nähe die Preise auslesen.
Da mich von clever-tanken die folgende Preise von Benzin Diesel LPG und ggf. für die Zukunft Elektro interessieren. Dazu würde ich gerne die dort aufgelisteten Preise haben.Wenn ich in den Seiten Quelltext der Tankstelle schaue habe ich dort eine Verschachtelung ausfindig gemacht.
In <div class="price-row row d-flex align-items-center"> wird wohl immer ein Spritpreis „verschachtelt“.
der Name ist in <div class="price-type-name"> zu finden
und der passende Preis in <span id="current-price-2"> (Hier wechselt die Nummer bei current-price von Tankstelle zu Tankstelle – da die eine vielleicht eine Spritsorte nicht hat die eine andere aber hat.Wie würdet ihr die abfrage realisieren um mit NodeRed die Werte zu erhalten? Ich scheiter daran das current-price immer eine fortlaufende Zahl hat.
beispiel quellcode.txt
Gruß ArminEdit 12.09.2022 - Die Schriftliche genehmigung von Clever-Tanken zur abfrage der Werte liegt mir vor.
-
@merlin2k11 sagte in Preisabfrage von clever-tanken:
ich würde gerne von Tankstellen hier in der nähe die Preise auslesen.
warum nicht mit dem Tankerkönig Adapter?
und bitte keine externen Hoster für den Quelltext!
bitte direkt hier im Forum hochladen, entweder als code in code-tags und Spoiler, oder wenn dafür zu groß als txt - Anhang -
@homoran
Hallo Homoran, der Quellcode ist nun in einer TXT.Warum nicht von Tankerkönig? Das liegt an den genannten Kraftstoffen... auf Tankerkönig gibt es kein LPG. auch kein Strom
Nur da wir hier 3 LPG Autos haben, ist das das was mich am meisten interessiert. Sprit ist da nur "nebensächlich" und wird eh nur alle 3-4 Monate gebraucht.
Daher ist der Tanker"König" gar nicht so toll wie der Name sagt.
-
Ich habe es noch nicht schön zusammen:
Man muss die beiden Arrays nur noch zusammenbringen - das überlege ich noch:
Im Prinzip wenn die Reihenfolge gleich blieb - dann kann man ein statisches Objekt draus machen - da dann Diesel immer Postition 0 und LPG auf Position 5.
-
@mickym vielen dank
das schaut soweit schon gut aus.Danke
-
@merlin2k11 sagte in Preisabfrage von clever-tanken:
Daher ist der Tanker"König" gar nicht so toll wie der Name sagt.
dafür hat Herr Kurz als erster eine API zur Abfrage bereitgestellt, während bei clever tanken in den AGB steht
Insbesondere ist es nicht gestattet, eigene Robots, Webcrawler oder sonstige Automatismen zu programmieren und die Inhalte von clever-tanken.de systematisch und umfassend in anderen Medien darzustellen oder für sonstige Zwecke zu extrahieren und zu verarbeiten.
-
@merlin2k11 So ich bin einfach zu blöde für JSONATA manchmal - nun habe ich es wieder mit einer function Node gemacht. Um beides zu synchronisieren wird das Ganze über Flow-Variablen synchronisiert:
-
@homoran Ich verstehe diese Diskussion nicht - es geht darum, wie man aus einer HTML Seite mit Node-Red ähnlich wie mit dem Parser Daten auslesen und aufbereiten kann. Der Inhalt ist mir wurscht - man kann ja die Überschrift ändern und schreiben
Website mit NodeRed parsen
Aber ansonsten halte ich mich da raus - ich hab nun eine technische Lösung präsentiert und gut ist.
-
@homoran sagte in Werte auslesen von Webseite:
und bitte keine externen Hoster für den Quelltext!
doch, wenn sie regex101 direkt nehmen dann schon
dort kann man wunderschön einen link auf seine gespeicherten daten speichern -
@mickym Wenn es nur um Jsonata geht, da kann ich helfen, was nicht heißt, dass es nicht noch einfacher geht.
Gruß
Reiner -
@oliverio Es geht darum, dass Files (oder auch Bilder) vom extern Hoster auch mal gelöscht oder der Link geändert werden könnte. Dann ist das Anhängsel hier im Thread wertlos, da es sich nicht mehr öffnen lässt. Was direkt im Filesystem des Forums liegt, bleibt auch da, bislang auch nach Umzügen zu anderen Hostern.
Deshalb sollte man immer Anhänge forenintern speichern und verlinken.Gruss, Jürgen
-
@rewenode Ach schön dass Du Dich meldest - mein JSONATA Lehrer. Ich kanns nur leider nicht importieren - da Du den Export nicht in CodeTags gepackt hast und dann interpretiert der Browser irgendwelche Zeichen. Kannst Du es nochmal in CodeTags exportieren?
Ja und war mir neu, wie oder dass man mehrere Abschnitte in der html node kombinieren kann.
So und die größte Herausforderung ist aber ken Array als Text, sondern ein Objekt mit den Kraftstoffen als Eingenschaften des Objektes wie bei mir unten.
Also Ergebnis, sollte schon so aussehen:
Ich scheitere immer daran die Objektingenschaften durch zu iterieren bzw. mappen.
Aber vielleicht kannst Du ja erst mal Deinen Flow nochmal in CodeTags packen, damit ich es mir in Ruhe anschauen kann, aber wie gesagt Ziel wäre EIN Objekt mit den entsprechenden Eigenschaften zu haben.
-
@mickym sagte in Werte auslesen von Webseite:
Ich kanns nur leider nicht importieren - da Du den Export nicht in CodeTags gepackt hast und dann interpretiert der Browser irgendwelche Zeichen. Kannst Du es nochmal in CodeTags exportieren?
Oh, sorry ;-( Schau mal ob es jetzt geht. Hab deb Beitrag geändert.
Gruß
Reiner -
@rewenode Ja jetzt ist die Change-Node solo drin und das wichtigste ist mit dem Code:
( $art := $filter(payload,function( $v,$i){ ($i)%2=0 }); $preis := $map($filter(payload,function( $v,$i){ ($i)%2=1 }),function($v,$i){ $split($v,"\n")[2].$trim().$number() }) ; $map($art,function($v,$i){ $v & ": " & $preis[$i] }) )
Allerdings stimmt das Ergebnis nicht.
Schön wäre wie gesagt ein Objekt - Ok das bekomme ich nun auch ohne Flow variablen aber halt mit JS hin. Ich schau mir das nochmal in Ruhe an. Hab mal den Output in eine InjectNode gemacht, um nicht immer die Webabfrage zu starten:
Momentan kommt bei Deinem Code - immer noch ein Array, statt eines Objektes raus und die Werte passen noch nicht. Aber ich werde es erst nochmal so in JS machen und dann unterhalten wir uns über JSONATA.
-
-
@rewenode Ja und nein - hab mal den Output in eine Inject Node gegeben, um nicht dauern die Webabfrage zu machen.
Klare Verbesserung aus der HTML Node - es werden nur die Textinhalte geholt.
Generell verstehe ich es - dass Du intern nun auch 2 Arrays machst, indem Du die geraden Elemente der $art zuweist und die ungeraden der $kraftstoff.
So bei dem Preis verstehe ich was Du machst - aber ich würde lieber Zahlen haben.Dann lass uns mal zu der Zeile kommen, die in meinen Augen Probleme macht:
$split($v,"\n")[2].$trim().$number()
Ich hab mal das formatNumber schon weggelassen, weil ich ja keine Strings haben möchte. Allerdings bekomme ich das Leerzeichen vor nicht weg.
Laut Beschreibung sollten ja auch führende Leerzeichen entfernt werden:
tut es aber nicht.
Das Einzige wie ich es nun hin bekomme, ist wenn man das Objekt zusammensetzt, das ich es dort nochmal mache:
$map( $art, function($v,$i){ $v & ": " & $preis[$i] } ){$split(":")[0]: $split(":")[1].$trim().$number()}
Das eigentlich geniale an JSONATA bzw. verwirrende ist die Iteration zur Objekterzeugung - das geht einfach noch nicht so recht in meinem Schädel.
Sprich wenn ich die splits weglasse hast Du einfach ein array in dem Du mit maps, die zusammengesetzt sind.
$map( $art, function($v,$i){ $v & ": " & $preis[$i] } )
ergibt also das Array.
Über das Verketten wird impliziert also jedes einzelne Array Element weiterverarbeitet.
$map( $art, function($v,$i){ $v & ": " & $preis[$i] } ){$split(":")[0]: $split(":")[1].$trim().$number()}
Das ist eigentlich das geniale an JSONATA - aber geht immer nicht so in den Kopf. Damit habe ich das gewünschte Ergebnis - wobei ich also
oben jetzt nur noch das $trim() stehen habe - da dort aus mir unerfindlichen Gründen die Zahlenumwandlung nicht geht:
Man kann das $trim() oben sogar ganz weglassen.
Also insgesamt sieht es nun so aus:
( $art := $filter( payload, function( $v,$i){ ($i)%2=0 } ); $preis := $map( $filter( payload, function( $v,$i){ ($i)%2=1 } ), function($v,$i){ $split($v,"\n")[2] } ) ; $map( $art, function($v,$i){ $v & ": " & $preis[$i] } ){$split(":")[0]: $split(":")[1].$trim().$number()} )
Der Punkt ist ja eigentlich ein Abkürzung für das map - wenn ich also diesen kleinen Punkt machen - wird quasi aus jeder Property wieder ein Array Element gebildet.
$map( $art, function($v,$i){ $v & ": " & $preis[$i] } ).{$split(":")[0]: $split(":")[1].$trim().$number()}
Dieser Punkt also ergibt dann:
Im Prinzip habe ich das verstanden - ich muss nur diese Verkettungen noch in meinen Kopf bekommen - jedenfalls ist diese Funktion schon mal zum Abspeichern.
Bleibt nur die Frage offen, warum funktioniert das Konvertieren in einen Zahlenwert oben nicht und unten schon???
EDIT: habe es auch mit dem Mapping oben versucht - das ergibt auch immer wieder Strings:
$preis := $map( $filter( payload, function( $v,$i){ ($i)%2=1 } ), function($v,$i){ $split($v,"\n")[2] } ).$trim().$number() ;
Erzeugt trotzdem:
Na zumindest funktioniert es wenn man es unten bei der Objekterstellung macht. Ich versuche das jetzt trotzdem nochmal mit regEx.
-
@rewenode Lieber Reiner - ich danke Dir wieder einmal so recht herzlich.
- ich bin immer noch verwirrt aber ich habe es nun in einen Einzeiler geschafft - danke für Deine Ideen. Hat mich Zeit gekostet - aber mit dem JSONATA Exerciser habe ich mich schrittweise vorgetastet.
Die magische Zeile (JSONATA ist magisch) lautet:
payload#$i[$i%2=0]{$$.payload[$i]:($$.payload[$i+1].$match(/\d\.\d+/).match.$number())}
Damit reduziert sich der ganze Flow auf:
Wenn man es als String dann auch noch mit den Nachkommastellen formatiert haben will kann man das dann ja noch einfach hinterher schieben.
payload#$i[$i%2=0]{$$.payload[$i]:($$.payload[$i+1].$match(/\d\.\d+/).match.$number().$formatNumber("#0.00"))}
NodeRed ist einfach genial.
- ich bin immer noch verwirrt aber ich habe es nun in einen Einzeiler geschafft - danke für Deine Ideen. Hat mich Zeit gekostet - aber mit dem JSONATA Exerciser habe ich mich schrittweise vorgetastet.
-
@mickym sagte in Werte auslesen von Webseite:
Die magische Zeile (JSONATA ist magisch) lautet
Sehr gut !!! Die Verlockung ist immer groß, JSONata-Konstrukte bis zum Einzeiler zu komprimieren, zumal es oft möglich ist.
Gründe, warum ich das oft versuche zu vermeiden sind:- ich will auch 2 Wochen später noch kapieren, was ich hier eigentlich gemacht habe;-) Und wenn da noch RegEx-Ausdrücke drin sind, geht es fast nicht mehr ohne sinnige Kommentare
- Man kann da schon ganz schön Zeit verdaddeln nur um ein paar Zeilen Code einzusparen
Aber Spaß kann das schon machen;-)
Gruß und schönen Sonntag
Reiner -
@rewenode Wenn ich Dich als Fachmann schon mal da habe.
Wenn ich, wie anfangs 2 Arrays habe - und möchte eines als topics bzw. property und das andere als Value nehmen:
{ "topic": [ "topic_01", "topic_02", "topic_03", "topic_04", "topic_05", "topic_06" ], "payload": [ 2.1, 1.96, 2.02, 2.11, 2.09, 1.08 ] }
dann bringe ich es nicht hin ohne $distinct-Function ein sauberes Objekt zu bekommen:
topic#$i@$t.payload@$p{$t:$p[$i]}
topic#$i@$t.payload@$p{$t:$distinct($p[$i])}
Gibts da noch eine andere Möglichkeit zu verhindern, dass der payload - mal Anzahl der Elemente in einem Array rauskommt. In dieser Variable $i scheint es ein ganzes Array .
Eventuell muss man da vorher was ausfiltern, weil im Beispiel - enthält das $i ja skalare Werte:
EDIT:
Ah ich habs
- muss man vorher ausfiltern.
topic#$i@$t.payload#$j@$p[$i=$j]{$t:$p}
Hier noch die praktische Anwendung in Node-Red:
Sorry dass ich den Thread etwas missbraucht habe. - Aber vielleicht ist das ja auch für andere interessant. Höre jetzt auch auf.
-
Danke Dir Reiner und auch einen schönen Sonntag.
-
@mickym So?
$.topic#$i{$$.topic[$i]:$$.payload[$i]}
Ja, sollte vlt. ein eigener Thread werden
Gruß
Reiner