Neue Version von HTTPMOD mit neuen Features zum Testen

Begonnen von StefanStrobel, 05 Dezember 2015, 08:31:32

Vorheriges Thema - Nächstes Thema

Gisbert

Hallo,

ich benötige beim Modul HTTPMOD Hilfe bei der Definition eines Regex.
Ich fokussiere mich mal auf das Wesentliche und komme gleich zur Frage.

Im Quelltext der Seite: https://www.clever-tanken.de/tankstelle_details/17099 wird mit Reading reading01Regex nach folgendem Muster gesucht:
"price-type-name">Diesel</div>[\d\D]{700,900}"current-price-.">([0-9\.]+[^0-9]+suffix-price-.">[0-9])
Den Ausdruck "price-type-name">Diesel</div> findet man im Quelltext und "current-price-1"> gefolgt von dem interessierendem Dieselpreis. Anschließend wird nach suffix-price-."> gesucht und zum 1. Ergebnis dazu addiert.
Dieser Regex funktioniert tadellos, also keine Klagen.

Anders sieht es hier aus. Auf der Seite: https://kurse.boerse.ard.de/ard/mobile/index.htn?mobilRedirect=1 wird versucht mit folgendem Regex den Dow Jones auszulesen:
Jones</span>[\d\D]{700,900}class="quote">(\d+\.\d+\,\d+)
Das funktioniert aber gar nicht. Eigentlich steht der interessierende Wert eine Zeile unter dem 1. Suchfragment Jones</span>

Kann mir hier jemand helfen?
Viele Grüße
Gisbert
Aktuelles FHEM | PROXMOX | Fujitsu Futro S740 | Debian 12 | UniFi | Homematic, VCCU, HMUART | ESP8266 | ATtiny85 | Wasser-, Stromzähler | Wlan-Kamera | SIGNALduino, Flamingo Rauchmelder FA21/22RF | RHASSPY

amenomade

Zitat von: Gisbert am 08 Mai 2020, 19:28:03
Eigentlich steht der interessierende Wert eine Zeile unter dem 1. Suchfragment Jones</span>
Dann musst Du wahrscheinlich den "s" Modifier benutzen. reading01Regopt oder
(?s)Jones</span>[\d\D]{700,900}class="quote">(\d+\.\d+\,\d+)
und auch evtl. die \n irgendwie noch matchen.
Pi 3B, Alexa, CUL868+Selbstbau 1/2λ-Dipol-Antenne, USB Optolink / Vitotronic, Debmatic und HM / HmIP Komponenten, Rademacher Duofern Jalousien, Fritz!Dect Thermostaten, Proteus

Gisbert

Hallo amenomade,

danke für den Gedankenanstoß, ich hab mit regex101.com getestet und kann das Problem jetzt näher eingrenzen.

Gematcht werden soll folgender Ausdruck, der Leerzeichen und einen nicht sichtbaren Zeilenumbruch enthält. Die back slash in <\span> und <br\> kann man durch einen Punkt (.) abfragen, ebenso das einzelne Leerzeichen zwischen span und class.

Was fehlt ist der nicht sichtbare Zeilenumbruch und die Leerzeichen - im Regex durch 3 ? ? ? dargestellt, für die ich noch keine Lösung habe.

Soll gematcht werden:
Jones</span><br/>
                <span class="quote">24.324,64

Regex:
Jones<.span><br.>???<span.class="quote">(\d+\.\d+\,\d+)

Viele​ Grüße​ Gisbert​
Aktuelles FHEM | PROXMOX | Fujitsu Futro S740 | Debian 12 | UniFi | Homematic, VCCU, HMUART | ESP8266 | ATtiny85 | Wasser-, Stromzähler | Wlan-Kamera | SIGNALduino, Flamingo Rauchmelder FA21/22RF | RHASSPY

Christoph Morrison

Warum machst du es dir so schwer, das mit einem RE rauszupopeln, wenn du auch XPath nutzen kannst?


defmod general.test.tiefer_johannes HTTPMOD https://kurse.boerse.ard.de/ard/mobile/index.htn?mobilRedirect=1
attr general.test.tiefer_johannes userattr reading01Name reading01XPath
attr general.test.tiefer_johannes reading01Name dow_jones
attr general.test.tiefer_johannes reading01XPath //*[@id="content"]/div/div/div/div/div/div[1]/div/div[1]/a[2]/span[3]


ergibt:


   QUEUE:
   READINGS:
     2020-05-09 12:15:28   dow_jones       24.324,64
   REQUEST:

amenomade

#754
ZitatWas fehlt ist der nicht sichtbare Zeilenumbruch und die Leerzeichen - im Regex durch 3 ? ? ? dargestellt, für die ich noch keine Lösung habe.
Es fehlt
\s*?

Performanter ist:
Jones.*?quote">(\d+\.\d+\,\d+)
Sonst ist ja XPath eine gute Alternative... wenn die gesamte Struktur der Seite XPath-konform ist.
Pi 3B, Alexa, CUL868+Selbstbau 1/2λ-Dipol-Antenne, USB Optolink / Vitotronic, Debmatic und HM / HmIP Komponenten, Rademacher Duofern Jalousien, Fritz!Dect Thermostaten, Proteus

Gisbert

Hallo amenomade,
das funktioniert:
Jones<.span><br.>\s*?<span.class="quote">(\d+\.\d+\,\d+)
das funktioniert anscheinend auch:
Jones<.span><br.>\s*<span.class="quote">(\d+\.\d+\,\d+)
Das funktioniert (bei regex101.com) nicht:
Jones.*?quote">(\d+\.\d+\,\d+)

Hallo Christoph,
XPath schaue ich mir auch an, das ist für mich dann nochmals schwerer als Regex.

Viele​ Grüße​ Gisbert​
Aktuelles FHEM | PROXMOX | Fujitsu Futro S740 | Debian 12 | UniFi | Homematic, VCCU, HMUART | ESP8266 | ATtiny85 | Wasser-, Stromzähler | Wlan-Kamera | SIGNALduino, Flamingo Rauchmelder FA21/22RF | RHASSPY

Christoph Morrison

Zitat von: Gisbert am 09 Mai 2020, 14:21:01
XPath schaue ich mir auch an, das ist für mich dann nochmals schwerer als Regex.

Das sieht vielleicht so aus, aber tatsächlich ist es deutlich einfacher, einen XPath-Ausdruck zu bekommen der passt, als selbst eine RE zu bauen die passt. Alle modernen Browser bieten von Haus eine XPath-Unterstützung an oder zumindest gibt es für jeden Browser ein Plugin, mit dem du mit einem Kontext-Klick den XPath zu einem Element bekommst.

Eine passende Regex könnte so aussehen (hat mich mehr Zeit gekostet als die XPath-Expression ;-)):


Jones[^0-9]+([0-9]+\.[0-9,]+)


Mein Device sieht jetzt so aus:


defmod general.test.tiefer_johannes HTTPMOD https://kurse.boerse.ard.de/ard/mobile/index.htn?mobilRedirect=1
attr general.test.tiefer_johannes userattr reading01Name reading01XPath reading02Name reading02Regex
attr general.test.tiefer_johannes reading01Name dow_jones_xpath
attr general.test.tiefer_johannes reading01XPath //*[@id="content"]/div/div/div/div/div/div[1]/div/div[1]/a[2]/span[3]
attr general.test.tiefer_johannes reading02Name dow_jones_re
attr general.test.tiefer_johannes reading02Regex Jones[^0-9]+([0-9]+\.[0-9,]+)


Und ergibt folgendes (Auszug):

   READINGS:
     2020-05-09 15:10:28   dow_jones_re    24.324,64
     2020-05-09 15:10:28   dow_jones_xpath 24.324,64

Gisbert

Hallo Christoph,

ich hab ein Addon mit XPath in Firefox installiert, dann musste man aber noch auf dem Fhem-Server (Debian) ein Paket (sudo apt-get install libhtml-treebuilder-xpath-perl) installieren, das angemeckert wurde.
Dannach war es sehr einfach, das ist vielleicht ein geiler Sch... 8)
So sieht es jetzt mit XPath aus:
defmod DowJones HTTPMOD https://kurse.boerse.ard.de/ard/mobile/index.htn?mobilRedirect=1 7200
attr DowJonesuserattr ... reading03Name reading03XPath reading04Name reading04XPath
...
attr DowJones reading03Name dow_jones_XPath
attr DowJones reading03XPath /html/body/div[2]/div/div/div/div/div/div[1]/div/div[1]/a[2]/span[3]
attr DowJones reading04Name dow_jones_perc_XPath
attr DowJones reading04XPath /html/body/div[2]/div/div/div/div/div/div[1]/div/div[1]/a[2]/span[4]

Auch die prozentuale Änderung lässt sich so erfassen.

Deine Definition sieht initial etwas anders aus: //*[@id="content"] ..., bei´m Firefox startet das Ganze mit /html/body/ ...
Was hat es damit auf sich?

Viele Grüße Gisbert
Aktuelles FHEM | PROXMOX | Fujitsu Futro S740 | Debian 12 | UniFi | Homematic, VCCU, HMUART | ESP8266 | ATtiny85 | Wasser-, Stromzähler | Wlan-Kamera | SIGNALduino, Flamingo Rauchmelder FA21/22RF | RHASSPY

Christoph Morrison

Zitat von: Gisbert am 09 Mai 2020, 16:47:38
Deine Definition sieht initial etwas anders aus: //*[@id="content"] ..., bei´m Firefox startet das Ganze mit /html/body/ ...
Was hat es damit auf sich?

Super dass du das probiert hast! Der Unterschied ist im Prinzip folgender, stell dir das als Baum vor, der beim Element /html beginnt. * sagt im Prinzip: Alles (wie bei RE) und in diesem Falle alles bis zu einem Element mit der ID content (@ wie @tttribut) - das ist dann die Wurzel des Baumes. Praktisch eine Abkürzung. XPath ist sehr mächtig und es lohnt sich imho, XPath und XML zu verstehen, gerade wenn man im Web arbeitet. Der Dritte im Bunde ist dann XSLT - damit kann man dann einen XPath-Ausdruck benutzen um eine XML-Quelle in etwas anderes zu transformieren.

Gisbert

Hallo Christoph,

von Verstehen bin ich noch meilenweit entfernt, ich hab jetzt nur das brav ausgeführt, was du mir vorgegeben hast, und nur die kleinen Stolpersteine Firefox Addon und fehlendes Perl-Paket aus dem Weg geräumt.
Da ja offensichtlich die beiden Definitionen zum gleichen Ergebnis kommen, welche ist denn "besser" oder resourcenschonender oder gar schneller?
/html/body/div[2]/div/div/div/div/div/div[1]/div/div[1]/a[2]/span[3]
//*[@id="content"]/div/div/div/div/div/div[1]/div/div[1]/a[2]/span[3]


Viele Grüße Gisbert
Aktuelles FHEM | PROXMOX | Fujitsu Futro S740 | Debian 12 | UniFi | Homematic, VCCU, HMUART | ESP8266 | ATtiny85 | Wasser-, Stromzähler | Wlan-Kamera | SIGNALduino, Flamingo Rauchmelder FA21/22RF | RHASSPY

amenomade

#760
Zitat von: Gisbert am 09 Mai 2020, 14:21:01
Das funktioniert (bei regex101.com) nicht:
Jones.*?quote">(\d+\.\d+\,\d+)

Doch doch, aber wie schon erwähnt muss man in dem Fall den "s" Modifier nutzen.  Weil "." ohne "s" Modifier Zeilenumbrüche nicht matcht.
Also bei regex101 ganz rechts, statt/zu gm => s
In HttpMod RegOpt s
Oder "inline" in der Regex (?s)(?s)Jones.*?quote">(\d+\.\d+\,\d+)
Pi 3B, Alexa, CUL868+Selbstbau 1/2λ-Dipol-Antenne, USB Optolink / Vitotronic, Debmatic und HM / HmIP Komponenten, Rademacher Duofern Jalousien, Fritz!Dect Thermostaten, Proteus

Gisbert

Hallo amenomade,

vielen Dank für deine Erklärung. Damit dürften meine Fragen ausgiebig diskutiert sein, und mein Toolkasten Regex und XPath füllt sich zusehend.

Viele​ Grüße​ Gisbert​
Aktuelles FHEM | PROXMOX | Fujitsu Futro S740 | Debian 12 | UniFi | Homematic, VCCU, HMUART | ESP8266 | ATtiny85 | Wasser-, Stromzähler | Wlan-Kamera | SIGNALduino, Flamingo Rauchmelder FA21/22RF | RHASSPY

amenomade

#762
Bei XPath würde ich eher folgendes benutzen
//a[contains(., 'Jones')]/span[@class="quote"]
Somit bist Du m.M.n. weniger abhängig von der gesamte Stuktur der Webseite

Bedeutet : suche das "a" node, das "Jones" enthält, und nimm davon das "span" child mit class "quote"

Es wäre performanter und sicherer, statt contains(), span/text()="Dow Jones" zu benutzen aber leider ist es immer ein bisschen schwierig mit den HTML Entities wie &nbsp; umzugehen. Ich weiss nicht, was mit HTTPMOD funktionieren würde:
text()="Dow Jones" => mit "non-breakable space" (unter Windows mit Alt+0160 eingeben)
text()="Dow${nbsp}Jones"
text()="Dow&nbsp;Jones"
...
Pi 3B, Alexa, CUL868+Selbstbau 1/2λ-Dipol-Antenne, USB Optolink / Vitotronic, Debmatic und HM / HmIP Komponenten, Rademacher Duofern Jalousien, Fritz!Dect Thermostaten, Proteus

Gisbert

Hallo amenomade,

die Optionen mit text() habe ich probiert, die laufen aber nicht bei mir.

Eine Abfrage, die mich interessiert, steht weiter unten auf der Homepage und betrifft den Euro Stoxx50; diese braucht eine andere Abfrage.
Der Seitenquelltext dazu sieht wie folgt aus:
<a class="scrtyshortlist" href="https://kurse.boerse.ard.de/ard/mobile/kurse_einzelkurs_uebersicht.htn?i=159194">
                <div class="row cf">
                  <span class="name">Euro&nbsp;Stoxx&nbsp;50</span>
                  <div class="right">
                    <span class="change pos">+0,95%</span>
                    <span class="quote">2.908,11 </span>
                  </div>
                </div>
                <div class="row cf">
                  <span class="wkn"></span>
                  <span class="date">08.05.2020 | 17:50</span>
                  <span class="change_abs pos">+27,51</span>
                </div>
              </a>

class ="quote" steht 3 Zeilen tiefer als Euro oder Stoxx, wonach gesucht werden kann.

Hast du dazu auch eine Idee?

Viele​ Grüße​ Gisbert​
Aktuelles FHEM | PROXMOX | Fujitsu Futro S740 | Debian 12 | UniFi | Homematic, VCCU, HMUART | ESP8266 | ATtiny85 | Wasser-, Stromzähler | Wlan-Kamera | SIGNALduino, Flamingo Rauchmelder FA21/22RF | RHASSPY

amenomade

Natürlich habe ich eine Idee.
Aber wäre es nicht besser, wenn Du es selbst versuchst?
Pi 3B, Alexa, CUL868+Selbstbau 1/2λ-Dipol-Antenne, USB Optolink / Vitotronic, Debmatic und HM / HmIP Komponenten, Rademacher Duofern Jalousien, Fritz!Dect Thermostaten, Proteus