Moin,
ich bin ein absoluter Neuling in Sachen Python
Möchte folgende Aufgabe lösen:
Ich habe einen Datenlogger von Photon, der an mein Netzwerk angeschlossen ist. Früher hat er die Daten an einen Server übertragen. Leider ist der Server down.
Auf den Logger kann ich über die IP-Adresse zugreifen (192.168.178.197). Nach der Passwortabfrage zeigt er die Einspeisedaten und u.a. die aktuelle Zeit an ebenso den Seiteninhalt. Auszug nachstehend.
<form action="/cgi-bin/menu.cgi" method="get">
<table border="0" summary="">
<input type="hidden" name="mode" value="data"><table border="0"><tr><td>Current Data ( all view only )</td></tr></table><br><br><table border="0">
<tr><td>Feed-in (kWh):</td><td><input type="text" size="15" value="00033308.02" readonly> </td></tr>
wie kann ich den Wert in der unteren Zeile nach "value" automatisiert auslesen (analog die Uhrzeit, die weiter unten steht) und speichern.
Weiter müsste die Routine z.B. alle 10 Minuten den Seiteninhalt aktualisieren.
Danke im voraus
Hans-Jürgen
Auslesen / Auswerten einer Webadresse im Heimnetz
Kleines Beispiel:
Code: Alles auswählen
from bs4 import BeautifulSoup
test = """<form action="/cgi-bin/menu.cgi" method="get">
<table border="0" summary="">
<input type="hidden" name="mode" value="data"><table border="0"><tr><td>Current Data ( all view only )</td></tr></table><br><br><table border="0">
<tr><td>Feed-in (kWh):</td><td><input type="text" size="15" value="00033308.02" readonly> </td></tr>"""
soup = BeautifulSoup(test, "html.parser")
value = soup.find_all("input")[1].get('value')
print(value)
Moin,
danke für die schnellen Tipps. Habe es zwischenzeitlich ganz gut mit "requests" gelöst. Daten werden regelmäßig ausgelesen und gespeichert (die auskommentierten Zeilen sind während des Testens entstanden, ebenso die Print-Ausgaben):
import requests
import time
import csv
index = 0
# range zeit in sekunden, 1 Jahr hat 1.314.000 sekunden
for i in range(100000):
# sleep anpassen sekunden
time.sleep(60)
r = requests.get('http://192.168.178.197/cgi-bin/menu.cgi?mode=data' , auth=('root' , 'xxxx'))
# die drei zeilen können gelöscht werden; der Bereich [xxxx:yyyy] muss für andere Daten angepasst werden
# bei 0 bis 2000 wird der gesamte Seiteninhalt angezeigt
# print (r.text[1208:1218])
# print (r.text[1852:1860])
# print (r.text[1865:1873])
kwH = (r.text[1208:1218])
Datum = (r.text[1852:1860])
Zeit = (r.text[1865:1873])
print ('kwH' ,kwH)
print ('Datum' , Datum)
print ('Zeit' , Zeit)
print (' ')
index = index + 1
print ('index' , index)
row = [index, Datum , Zeit, kwH]
with open('werte.csv', 'a') as csvFile:
writer = csv.writer(csvFile)
writer.writerow(row)
csvFile.close()
jetzt fehlt mir nur noch ein Tipp, wie ich ich die kwH gleich als Zahl (mit Dezimalkomma statt ...punkt) und nicht als Textstring bekomme. Dann kann ich den Nachbearbeitungsbedarf reduzieren.
Hans-Jürgen
danke für die schnellen Tipps. Habe es zwischenzeitlich ganz gut mit "requests" gelöst. Daten werden regelmäßig ausgelesen und gespeichert (die auskommentierten Zeilen sind während des Testens entstanden, ebenso die Print-Ausgaben):
import requests
import time
import csv
index = 0
# range zeit in sekunden, 1 Jahr hat 1.314.000 sekunden
for i in range(100000):
# sleep anpassen sekunden
time.sleep(60)
r = requests.get('http://192.168.178.197/cgi-bin/menu.cgi?mode=data' , auth=('root' , 'xxxx'))
# die drei zeilen können gelöscht werden; der Bereich [xxxx:yyyy] muss für andere Daten angepasst werden
# bei 0 bis 2000 wird der gesamte Seiteninhalt angezeigt
# print (r.text[1208:1218])
# print (r.text[1852:1860])
# print (r.text[1865:1873])
kwH = (r.text[1208:1218])
Datum = (r.text[1852:1860])
Zeit = (r.text[1865:1873])
print ('kwH' ,kwH)
print ('Datum' , Datum)
print ('Zeit' , Zeit)
print (' ')
index = index + 1
print ('index' , index)
row = [index, Datum , Zeit, kwH]
with open('werte.csv', 'a') as csvFile:
writer = csv.writer(csvFile)
writer.writerow(row)
csvFile.close()
jetzt fehlt mir nur noch ein Tipp, wie ich ich die kwH gleich als Zahl (mit Dezimalkomma statt ...punkt) und nicht als Textstring bekomme. Dann kann ich den Nachbearbeitungsbedarf reduzieren.
Hans-Jürgen
- __blackjack__
- User
- Beiträge: 13079
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@hjliedtke: `index` hat immer den gleichen Wert wie `i` und `i` wird nirgends verwendet, die ``for``-Schleife sollte also `index` als Laufvariable verwenden und die Initialisierung von `index` mit 0 sowie das manuelle hochzählen kann man sich dann sparen.
Der Kommentar für die ``for``-Schleife erscheint mir sehr willkürlich weil der nicht wirklich etwas mit dem Code zu tun hat. Hatte er vielleicht mal, aber weder die Zahl noch Sekunden hat irgendetwas mit der tatsächlichen Anzahl der Schleifendurchläufe noch mit der Wartezeit für einen Schleifendurchlauf zu tun.
Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase).
Namen sollten auch nicht nur einen Buchstaben lang sein, oder aus Abkürzungen bestehen. Wenn man `response` meint, sollte man nicht nur `r` schreiben.
Wenn man ``with`` verwendet braucht man kein `close()` mehr auf der Datei aufrufen. Genau deswegen verwendet man ja ``with``.
Das ausschneiden per Indexwerte ist extrem fragil. Bei HTML sollte man sich, wie ja schon vorgeschlagen wurde, mit einem HTML-Parser an der Struktur des Dokuments orientieren.
Datum und Zeit sind eigentlich *ein* Wert, der nicht in zwei getrennten Spalten gespeichert werden sollte.
Zwischenstand:
Der Kommentar für die ``for``-Schleife erscheint mir sehr willkürlich weil der nicht wirklich etwas mit dem Code zu tun hat. Hatte er vielleicht mal, aber weder die Zahl noch Sekunden hat irgendetwas mit der tatsächlichen Anzahl der Schleifendurchläufe noch mit der Wartezeit für einen Schleifendurchlauf zu tun.
Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase).
Namen sollten auch nicht nur einen Buchstaben lang sein, oder aus Abkürzungen bestehen. Wenn man `response` meint, sollte man nicht nur `r` schreiben.
Wenn man ``with`` verwendet braucht man kein `close()` mehr auf der Datei aufrufen. Genau deswegen verwendet man ja ``with``.
Das ausschneiden per Indexwerte ist extrem fragil. Bei HTML sollte man sich, wie ja schon vorgeschlagen wurde, mit einem HTML-Parser an der Struktur des Dokuments orientieren.
Datum und Zeit sind eigentlich *ein* Wert, der nicht in zwei getrennten Spalten gespeichert werden sollte.
Zwischenstand:
Code: Alles auswählen
#!/usr/bin/env python3
import csv
import time
import requests
def main():
for index in range(100_000):
time.sleep(60)
response = requests.get(
"http://192.168.178.197/cgi-bin/menu.cgi?mode=data",
auth=("root", "xxxx"),
)
response.raise_for_status()
#
# TODO Robuster mit einem HTML-Parser lösen.
# TODO Datum und Zeit sind *ein* Wert, der Zeitpunkt der Messung, und
# sollte in einer Spalte gespeichert werden.
#
verbrauch = response.text[1208:1218]
datum = response.text[1852:1860]
zeit = response.text[1865:1873]
print("kwH", verbrauch)
print("Datum", datum)
print("Zeit", zeit)
print()
print("index", index)
with open("werte.csv", "a") as csv_file:
csv.writer(csv_file).writerow([index, datum, zeit, verbrauch])
if __name__ == "__main__":
main()
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
@blackjack
Vielen Dank für den Kurzkursus ) - wie geschrieben, ich bin absoluter Neuling.
Die vermeintliche Fragilität der Indexwerte besteht nicht, sie stehen immer an der gleichen Stelle. Insofern wäre es auch für mich recht leicht, die anderen Werte nach dem gleichen Schema zu extrahieren. Dazu brauche ich mir dann nicht noch das Parsing anlesen.
Datum und Zeit: letztlich ist es die Frage, ob und wie ich die Daten weiter verarbeiten möchte. Ist doch letztlich egal.
Meine eigentliche Frage ging aber dahin, wie ich die kwH in eine Dezimalzahl - möglichst mit Komma und nicht mit Punkt umwandeln und speichern kann.
Wenns nicht mit relativ wenig Aufwand gehen sollte, wandle ich sie in eine int- Zahl um und begnüge mich damit.
Hans-Jürgen
NS
Eigentlich für die Fragestellung unerheblich, aber wie bekomme ich den Code so schön kopiert wie in Deinem Beispiel. Mein Copy u. Paste sieht ja längst nicht so gut aus.
Vielen Dank für den Kurzkursus ) - wie geschrieben, ich bin absoluter Neuling.
Die vermeintliche Fragilität der Indexwerte besteht nicht, sie stehen immer an der gleichen Stelle. Insofern wäre es auch für mich recht leicht, die anderen Werte nach dem gleichen Schema zu extrahieren. Dazu brauche ich mir dann nicht noch das Parsing anlesen.
Datum und Zeit: letztlich ist es die Frage, ob und wie ich die Daten weiter verarbeiten möchte. Ist doch letztlich egal.
Meine eigentliche Frage ging aber dahin, wie ich die kwH in eine Dezimalzahl - möglichst mit Komma und nicht mit Punkt umwandeln und speichern kann.
Wenns nicht mit relativ wenig Aufwand gehen sollte, wandle ich sie in eine int- Zahl um und begnüge mich damit.
Hans-Jürgen
NS
Eigentlich für die Fragestellung unerheblich, aber wie bekomme ich den Code so schön kopiert wie in Deinem Beispiel. Mein Copy u. Paste sieht ja längst nicht so gut aus.
- __blackjack__
- User
- Beiträge: 13079
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@hjliedtke: Das die immer an der gleichen Stelle stehen ist halt genau das was man nicht wirklich als gegeben ansehen sollte.
Für eine Umwandlung in eine Zahl ist der Dezimalpunkt schon das richtige, denn ein Komma versteht Python's `float()` oder `decimal.Decimal()` an der Stelle nicht. Ich würde das einmal mit `float()` parsen, dann wieder in eine Zeichenkette umwandlen und den Dezimalpunkt durch ein Komma ersetzen.
Und für Datum und Zeit gibt es was im `datetime`-Modul.
Für eine Umwandlung in eine Zahl ist der Dezimalpunkt schon das richtige, denn ein Komma versteht Python's `float()` oder `decimal.Decimal()` an der Stelle nicht. Ich würde das einmal mit `float()` parsen, dann wieder in eine Zeichenkette umwandlen und den Dezimalpunkt durch ein Komma ersetzen.
Und für Datum und Zeit gibt es was im `datetime`-Modul.
Code: Alles auswählen
#!/usr/bin/env python3
import csv
import time
from datetime import datetime as DateTime
import requests
def main():
for index in range(100_000):
time.sleep(60)
response = requests.get(
"http://192.168.178.197/cgi-bin/menu.cgi?mode=data",
auth=("root", "xxxx"),
)
response.raise_for_status()
#
# TODO Robuster mit einem HTML-Parser lösen.
#
verbrauch = float(response.text[1208:1218])
datum = DateTime.strptime(response.text[1852:1860], "%d.%m.%Y")
zeit = DateTime.strptime(response.text[1865:1873], "%H:%M")
zeitstempel = DateTime.combine(datum.date(), zeit.time())
print("kwH", verbrauch)
print("Datum", datum)
print("zeitstempel", zeitstempel)
print()
print("index", index)
with open("werte.csv", "a") as csv_file:
csv.writer(csv_file).writerow(
[
index,
zeitstempel.isoformat(),
format(verbrauch, ".2f").replace(".", ","),
]
)
if __name__ == "__main__":
main()
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Das mit dem Zeitstempel brauche ich nicht - funktioniert bei mir auch nicht richtig (es braucht aber auch nicht korrigiert werden). Diese Fehlermeldung ist mir auch zu kryptisch.
Traceback (most recent call last):
File "/home/pi/testblackjack.py", line 18, in <module>
zeit = DateTime.strptime(response.text[1865:1873], "%H:%M")
File "/usr/lib/python3.7/_strptime.py", line 577, in _strptime_datetime
tt, fraction, gmtoff_fraction = _strptime(data_string, format)
File "/usr/lib/python3.7/_strptime.py", line 362, in _strptime
data_string[found.end():])
ValueError: unconverted data remains: :55
Aber die Formatierung mit
format(verbrauch, ".2f").replace(".", ","),
ist genau das, was ich meinte.
Nochmals vielen Dank und einen schönen Abend
Hans-Jürgen
Traceback (most recent call last):
File "/home/pi/testblackjack.py", line 18, in <module>
zeit = DateTime.strptime(response.text[1865:1873], "%H:%M")
File "/usr/lib/python3.7/_strptime.py", line 577, in _strptime_datetime
tt, fraction, gmtoff_fraction = _strptime(data_string, format)
File "/usr/lib/python3.7/_strptime.py", line 362, in _strptime
data_string[found.end():])
ValueError: unconverted data remains: :55
Aber die Formatierung mit
format(verbrauch, ".2f").replace(".", ","),
ist genau das, was ich meinte.
Nochmals vielen Dank und einen schönen Abend
Hans-Jürgen
- __blackjack__
- User
- Beiträge: 13079
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@hjliedtke: Na offensichtlich konnte von der Zeit ":55" am Ende nicht konvertiert werden. Ist also nicht "%H:%M" sondern "%H:%M:%S". Die Formate waren ja auch nur geraten, das gab's ja keine Beispiele.
Was Du alles so nicht brauchst — es ist so halt nicht robust, prüft die Daten nicht, und schreibt ein Format das Daten nicht in einer Form enthält die man gut weiterverarbeiten kann.
Was Du alles so nicht brauchst — es ist so halt nicht robust, prüft die Daten nicht, und schreibt ein Format das Daten nicht in einer Form enthält die man gut weiterverarbeiten kann.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman