csv Dateien herunterladen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Schlangenmensch
User
Beiträge: 73
Registriert: Freitag 18. Februar 2022, 10:13

Guten Abend,

ich habe vor kurzem einen Wasserzähler mit vorbereiteter AI on the EDGE Software in Betrieb genommen. Alles funktioniert bis jetzt einwandfrei. Nun wollte ich jedoch die täglich gespeicherten Daten vom "Fileserver" herunterladen.

Leider muß ich jede einzelne Datei (data_2025-01-01) usw. per Ziel speichern unter über das WLAN herunterladen.

Nun wollte ich mit einem kleinen Python-Script die Dateien automatisch nacheinander herunterladen, jedoch fehlt mir hierzu die Idee, wie ich das Datum in der URL sowie am Zielort erhöhen kann.

Bis jetzt bin ich nur zum Download einzelner csv.Dateien gekommen.

hat hier jemand einen Tip für mich?

Code: Alles auswählen

import requests

req = requests.get('http://192.168.178.33/fileserver/log/data/data_2025-01-03.csv')


url_content = req.content


with open("/home/****/****/Wasserzähler/data_2025-01-03.csv", 'wb') as csv_file:

    csv_file.write(url_content)

Benutzeravatar
sparrow
User
Beiträge: 4525
Registriert: Freitag 17. April 2009, 10:28

Formatieren einer Zeichenkette: f-Strings.
Alles um Datum und Zeit findest du im datetime Modul. Auf ein bestehendes Datum kannst du einfach ein timdelta mit einem Tag addieren.

Code: Alles auswählen

>>> from datetime import date as Date
>>> from datetime import timedelta as TimeDelta
>>> today = Date.today()
>>> tomorrow = today + TimeDelta(days=1)
>>> print(tomorrow)
2025-01-13
>>>
Schlangenmensch
User
Beiträge: 73
Registriert: Freitag 18. Februar 2022, 10:13

Danke für die schnelle Antwort, jetzt muß ich es "nur" noch hinbekommen die URL bzw. den Tag im Datum nach einem Schleifendurchlauf zu erhöhen.

Ich wurstel mich mal durch. :oops:
Benutzeravatar
Dennis89
User
Beiträge: 1517
Registriert: Freitag 11. Dezember 2020, 15:13

Hallo,

ergänzend der Link zur Doku


Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
DeaD_EyE
User
Beiträge: 1219
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Code: Alles auswählen

from datetime import date as Date
from pathlib import Path
from urllib.request import URLError, urlopen


def download_by_date(date: Date):
    file = f"data_{date}.csv"
    url = f"http://192.168.178.33/fileserver/log/data/{file}"
    # Angaben korrigieren
    server_file = Path.home().joinpath("XXXX", "Wasserzähler", file)

    print(f"{file=}")
    print(f"{url=}")
    print(f"{server_file=}")

    try:
        response = urlopen(url)
    except URLError:
        print(f"Konnte keine Verbindung zum Server aufbauen")
        return

    if server_file.exists():
        print("Datei existiert bereits auf dem Server und wird nicht heruntergeladen")
        return

    with server_file.open("w") as fd:
        while chunk := response.read(1024):
            fd.write(chunk)


if __name__ == "__main__":
    heute = Date.today()
    download_by_date(heute)

Das Modul csv wird für den Download nicht benötigt. Wenn man csv lesen oder schreiben will, benötigt man das Modul csv.
Für den Download kann man auch urllib.request.urlopen verwenden. Ist geschmackssache. Das Modul requests ist halt eine weitere Abhängigkeit.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Schlangenmensch
User
Beiträge: 73
Registriert: Freitag 18. Februar 2022, 10:13

Vielen Dank für die Lösung.

Hätte man auch die URL in einer Liste speichern können und den Tag über ne Schleife je um 1 erhöhen und im Anschluß die Dateien nacheinander zu speichern? Ich möchte die Daten sowieseo nur pro Monat ziehen.

Wäre vermutlich totaler Murks, würde mich jedoch interessieren.
Benutzeravatar
DeaD_EyE
User
Beiträge: 1219
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Code: Alles auswählen

datetime.date.today()
gibt immer das aktuelle Datum aus.
Mit timedelta und datetime kann man auch addieren und subtrahieren.

Im alten Code sind übrigens noch Fehler drin. Unter anderem wird die Datei im Text-Modus geöffnet, was falsch ist, da response.read(...) bytes ausgibt. Mit dem alten Code müsste ein TypeError ausgelöst werden.

Hier ein Beispiel, um das Datum zu inkrementieren und mehrere Dateien herunterzuladen.

Code: Alles auswählen

from datetime import date as Date
from datetime import timedelta as TimeDelta
from http.client import HTTPResponse
from pathlib import Path
from urllib.error import URLError
from urllib.request import urlopen


def download_file(response: HTTPResponse, file: Path):
    # im alten Beispiel habe ich das b vergessen
    # dann wird die Datei im Textmodus geöffnet
    # und erwartet dann str
    # aber response.read(...) liefert bytes zurück,
    # also muss man auch bytes schreiben

    with file.open("wb") as fd:
        while chunk := response.read(1024):
            fd.write(chunk)


def download_range(from_date: Date, to_date: Date):
    ONE_DAY = TimeDelta(days=1)
    server_path = Path.home().joinpath("XXXX", "Wasserzähler")
    current_date = from_date

    while from_date <= current_date <= to_date:
        file = f"data_{current_date}.csv"
        url = f"http://192.168.178.33/fileserver/log/data/{file}"
        server_file = server_path / file

        print(f"{file=}")
        print(f"{url=}")
        print(f"{server_file=}")

        try:
            response = urlopen(url, timeout=2)
        except URLError:
            print(f"Konnte keine Verbindung zum Server aufbauen:", url, end="\n\n")
            current_date += ONE_DAY
            continue

        if server_file.exists():
            print(
                f"Datei '{server_file}' existiert bereits auf dem Server und wird nicht heruntergeladen",
                end="\n\n",
            )
            current_date += ONE_DAY
            continue

        download_file(response, server_file)
        current_date += ONE_DAY
        print()


if __name__ == "__main__":
    bis = Date.today()
    von = bis - TimeDelta(days=31)
    download_range(von, bis)
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Schlangenmensch
User
Beiträge: 73
Registriert: Freitag 18. Februar 2022, 10:13

Nochmals vielen herzlichen Dank für die verbesserte Lösung. Ich werde sie bei Gelegenheit testen, versuche aber erst einmal meinen Murks zu Ende zu bringen um zu sehen ob das überhaupt auch funktioniert hätte. :oops:
Sirius3
User
Beiträge: 18250
Registriert: Sonntag 21. Oktober 2012, 17:20

@DeaD_EyE: jetzt hast Du ein wunderbares Beispiel geliefert, warum man `continue` nicht verwenden sollte. Kann man Dir ja hundert mal schreiben, ich hoffe jetzt, dass Du es an Deinem eigenen Code selbst erkennst.
Es ist nicht nötig, shutil.copyfileobj nochmal nachzuprogrammieren.
Konstanten definiert man normalerweise am Anfang der Datei, damit man sie leicht finden und anpassen kann.
In der while-Schleife kann per Definition niemals die untere Bedingung falsch sein.
Im if-__name__-Block sollte wirklich nur ein Funktionsaufruf stehen.
Berücksichtig man das alles, kommt man ungefähr hier raus:

Code: Alles auswählen

from datetime import date as Date, timedelta as TimeDelta
from pathlib import Path
from urllib.error import URLError
from urllib.request import urlopen
from shutil import copyfileobj

ONE_DAY = TimeDelta(days=1)
SERVER_PATH = Path.home() / "XXXX" / "Wasserzähler"
URL = "http://192.168.178.33/fileserver/log/data/"

def download_range(from_date, to_date):
    current_date = from_date

    while current_date <= to_date:
        file = f"data_{current_date}.csv"
        url = f"{URL}/{file}"
        server_file = server_path / file

        print(f"{file=}")
        print(f"{url=}")
        print(f"{server_file=}")

        try:
            response = urlopen(url, timeout=2)
        except URLError:
            print("Konnte keine Verbindung zum Server aufbauen:", url)
        else:
            if server_file.exists():
                print(
                    f"Datei '{server_file}' existiert bereits auf dem Server und wird nicht heruntergeladen"
                )
            else:
                with server_file.open("wb") as fd:
                    copyfileobj(response, fd)

        current_date += ONE_DAY
        print()


def main():
    bis = Date.today()
    von = bis - TimeDelta(days=31)
    download_range(von, bis)

if __name__ == "__main__":
    main()
Benutzeravatar
DeaD_EyE
User
Beiträge: 1219
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

@Sirius3 ich weiß, dass continue in diesem Fall nicht ideal war, da ich 2-mal die gleiche Zeile Code kopieren musste. Ist mir aber egal, da ich keine Zeit mehr hatte und fertig werden wollte. Du hast ja meine Fehler korrigiert und das reicht doch aus.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Antworten