Erfahrungen mit Puppeteer?

Begonnen von gestein, 28 August 2021, 12:41:55

Vorheriges Thema - Nächstes Thema

gestein

Hallo,

Ich versuche Informationen über meine Devolo Magic 2 in mein FHEM zu bekommen.
Anscheinend gibt es nur die http-Seite dafür - leider nix anders.

Leider wird die Seite über js-Scripte aufgebaut.
Damit kann man HTTPMOD nicht verwenden.

Schlussendlich habe ich verschiedene headless Browser ausprobiert.
Hat aber auch nicht geklappt.

Nun bin ich bei Googles Pupetteer.
Damit scheint es gut zu funktionieren, aber es gäbe nicht einige Details zu klären.
Und ich bin halt kompletter Neuling.

Die Seite von meinen Devolos kann ich schon mal aufrufen und es wird auch was gelesen.
Die Seite kann ich als Text oder als Screenshot abspeichern.
Allerdings wird zuerst verschiedene js-Scripte geladen und die zeigen dann erst eine Tabelle an.
Puppeteer wartet aber nicht, bis die Scripte die Seite geladen haben, sondern zeigt gleich die erste Seite an.
Dort steht dann halt ,,warten bis Daten geladen sind".

Gibt es hier jemanden, der sich mit Puppetteer auskennt und mir ein paar Tipps in die richtige Richtung zu geben könnte?

Danke, Lg, Gerhard

gestein

Hallo,

ich bin inzwischen etwas weitergekommen und kann von den Devolos-Seiten schon mal die Daten extrahieren.
Das Ganze läuft erst sehr rudimentär, aber prinzipiell geht es.

Mein Script schaut so aus:
'use strict';

const ventriloquist = require('puppeteer');

(async() => {
  const browser = await ventriloquist.launch({product: "chrome", executablePath: "/usr/bin/chromium",});
  const page = await browser.newPage();
//  Devolo URL has the format 'http://x.x.x.x/#/wifi/status';
  const pageURL = process.argv[2];

  process.on('unhandledRejection', (reason, p) => {
    console.error('Unhandled Rejection at: Promise', p, 'reason:', reason);
    browser.close();
  });

  await page.setViewport({ width: 1920, height: 1080 });
  await page.goto( pageURL,{
    waitUntil: 'networkidle0',
  });

  await page.goto( pageURL,{
    waitUntil: 'networkidle0',
  });

  await page.screenshot({path: 'puppetmaster.png'});
  var output = await page.evaluate(() => {
    return;
  });

//  const text = await page.$eval('*', el => el.innerText);
// ng-tns-0-0
//  const text = await page.content();
  const table = await page.$$eval('table tr td', tds => tds.map((td) => {
    return td.innerText;
  }));

  const fs = require('fs');
  fs.writeFileSync('./file.txt', table);

  process.stdout.write(table+'\n');

  await browser.close();
})();

Verbesserungen gerne willkommen ;-)

Momentan muss ich es noch händisch in der shell mit "node script.js <address of Devolo>" aufrufen.
Dann wird ein Screenshot abgespeichert, die Daten in einem File ausgegeben und gleichzeitig auch auf der Console.

Aber nun wird es spannend.
Denn wie soll ich die Daten in fhem bekommen.

Mir schwebt momentan vor, dass das script in einer Endlos-Schleife läuft, die Seite ausliest und immer wieder die Datei überschreibt.
Dann bräuchte ich eine Möglichkeit in fhem die Datei zu lesen und in Readings zu packen.
Oder ich rufe das über die in fhem eingebaute telnet-Schnittstelle auf.

Weiß jemand, wie man das am Besten angeht?
Was wäre der "richtige" Weg?

Und wie soll man die Endlos-Schleife beenden?
Gibt es da einen (Standard-)Mechanismus in Linux?

Danke für jeden Tipp.
lg, Gerhard

Christoph Morrison

Sicher, dass diese Javascripte nicht über eine API (XHR, etc.) mit einem Endpunkt kommunizieren, den du dann auch mit HTTPMOD/JSONMOD abfragen kannst?

gestein

Um ehrlich zu sein: da habe ich absolut keine Ahnung.
Soweit reicht mein Wissen bei weitem nicht.
Ich wüsste nicht mal, wie ich das überprüfen könnte.

Lg, Gerhard

Christoph Morrison

Hallo Gerhard,

schau z.B. mal hier: https://www.youtube.com/watch?v=nl8iKlo2NeM
Oder hier z.B. https://egghead.io/lessons/tools-examine-ajax-requests-with-chrome-devtools

Da suchst du dann, ob XHR-Request gemacht werden, irgendwo steht dann der Endpunkt und den kann man meistens auch direkt anzapfen.

Gruß
Christoph

gestein

Danke dafür. Das scheint doch in die richtige Richtung zu gehen.
Ich hatte mir das schon mal angeschaut ohne Zusammenhänge zu verstehen.
Die verstehe ich zwar immer noch nicht, aber eventuell tut sich da was auf ;-)

In dem Beitrag war ich schon mal dran.
https://forum.fhem.de/index.php/topic,119022.msg1134616.html#msg1134616

Es wird irgendwann sowas geschickt:
Request URL: http://192.168.0.x/ubus
Request Method: POST
Status Code: 200 OK
Remote Address: 192.168.0.x:80
Referrer Policy: strict-origin-when-cross-origin
Connection: Keep-Alive
Content-Type: application/json
Keep-Alive: timeout=20
Transfer-Encoding: chunked
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate
Accept-Language: de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7
Connection: keep-alive
Content-Length: 335
Content-Type: application/json
Host: 192.168.0.x
Origin: http://192.168.0.x
Referer: http://192.168.0.x/
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36
[{jsonrpc: "2.0", method: "call", id: "39b4a9b5-6c1b-46a9-9905-7e93fca6db98",...},...]
0: {jsonrpc: "2.0", method: "call", id: "39b4a9b5-6c1b-46a9-9905-7e93fca6db98",...}
id: "39b4a9b5-6c1b-46a9-9905-7e93fca6db98"
jsonrpc: "2.0"
method: "call"
params: ["f9e7152d5f824088d884982eb22af0fa", "network.info", "clients", {device: "ath1"}]
1: {jsonrpc: "2.0", method: "call", id: "05c259be-9d91-4d49-84e9-d4fcbc63ccd2",...}
id: "05c259be-9d91-4d49-84e9-d4fcbc63ccd2"
jsonrpc: "2.0"
method: "call"
params: ["f9e7152d5f824088d884982eb22af0fa", "network.info", "clients", {device: "ath0"}]


Und zurück kommt dann die Liste:
[{jsonrpc: "2.0", id: "39b4a9b5-6c1b-46a9-9905-7e93fca6db98",...},...]
0: {jsonrpc: "2.0", id: "39b4a9b5-6c1b-46a9-9905-7e93fca6db98",...}
id: "39b4a9b5-6c1b-46a9-9905-7e93fca6db98"
jsonrpc: "2.0"
result: [0, {clients: {BE:71:A0:93:85:52: {connected_time: 13388, rx: {rate: 585000}, tx: {rate: 650000}},...}}]


Aber wie kann ich das nutzen?

Danke, lg, Gerhard

Christoph Morrison

Im Prinzip musst du nun z.B. mit HTTPMOD den Browser simulieren. Dazu musst du rausfinden, welche der Header und welche Payload der Header wirklich haben muss um die benötigten Informationen rauszurücken. Im besten Falle gibt es irgendwo eine API-Beschreibung.

ubus hört sich nach µ-bus, also microbus, an: https://openwrt.org/docs/techref/ubus
Da gibt es auch eine Sektion über Zugriff via HTTP: https://openwrt.org/docs/techref/ubus#access_to_ubus_over_http

Dazu würde auch passen, dass JSONRPC 2.0 verwendet wird.

Ich kann leider fast nicht mehr dazu sagen, denn ich habe hier nirgendwo ein OpenWRT, geschweige denn Devolo Magic 2, laufen.

Beta-User

Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

gestein

Hallo,

Vielen Dank für die Hinweise.
Das mit den Ubus hatte ich gestern auch gefunden.
Und mit HTTPMOD bin ich schon verzweifelt  ;)

An meinem puppeteer hatte ich noch etwas weitergearbeitet und mittlerweile bekomme ich die Liste der mit dem jeweiligen AP verbundenen Geräte in fhem.
Aber alles sehr rudimentär und aufgrund des Overheads relativ langsam.

Eure Ansätze klingen sehr vielversprechend, aber mir fehlt dazu ziemlich viel Knowhow.

Mal sehen, ob ich da was im Winter machen kann.

Lg, Gerhard

Christoph Morrison


gestein

Im Prinzip ja.
Meine damaligen Versuche mit HTTPMOD habe ich leider aufgegeben, da fehlt mir einfach das Wissen.

Danach habe ich verschiedene Browser probiert und bin schlussendlich auf puppeteer gekommen.
Mit einigen Beispielen konnte ich damit nun zumindest die Daten in fhem bekommen.
Ist wahrscheinlich ein ziemlicher Overkill, aber immerhin bin ich damit zum Ziel gekommen.

Wenn das Ganze aber per UBUS/HTTPMOD/JSONMOD laufen würde, wäre das natürlich noch besser.
Lg, Gerhard


gestein

Nachdem nun die Abfragen mit Puppeteer laufen und ich die Daten in fhem bekomme, hat sich eine weitere Möglichkeit mit dem UBUS-Modul aufgetan.
Dank xenos1984 konnte ich schon mal Werte vom Devolo einlesen.
https://forum.fhem.de/index.php/topic,122943.0.html

Danke an alle!!

lg, Gerhard

Christoph Morrison

Du hast mir puppeteer gezeigt. Insofern habe auch ich zu danken.

gestein

Das ist schon ein sehr mächtiges Tool. Unglaublich was man da machen kann.
Immer wieder gerne. Freut mich, wenn ich auch mal was helfen konnte.