Datei von Webseite downloaden

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
tmessers
User
Beiträge: 28
Registriert: Dienstag 30. Oktober 2018, 21:08

Donnerstag 10. Dezember 2020, 15:14

Hallo liebe Python-Gemeinde,

ich habe eine Frage zum download von Dateien, die über eine website abrufbar sind.
Ich mache es mal praktisch.

Unter der url: "http://www.gesundheitsatlas-bw.de/datav ... &subsetId=" sind Daten zu Corona abrufbar.
Über einen Button lassen sich die Daten u.a. als Excel-Datei exportieren und herunterladen.
Die Datei trägt den Namen "dataView212_1.xls"
Als Quelle der Excel-Datei wird in deren Eigenschaften angegegeben:
"http://www.gesundheitsatlas-bw.de/data/ ... nces=13552, http://www.gesundheitsatlas-bw.de/datav ... &subsetId="

Ich möchte die Daten der Datei mit pandas weiterverarbeiten. Wer kann mir dabei helfen, wie ich die Daten aus der Excel-Datei auslesen kann.

Gruß

tmessers
Jankie
User
Beiträge: 592
Registriert: Mittwoch 26. September 2018, 14:06

Donnerstag 10. Dezember 2020, 15:17

mit pd.read_excel()? Oder wo konkrekt kommst du nicht weiter?
tmessers
User
Beiträge: 28
Registriert: Dienstag 30. Oktober 2018, 21:08

Donnerstag 10. Dezember 2020, 15:33

Das Problem ist der Pfadname. Wie lautet der Pfad, unter welchem die Excel-Datei abgelegt ist?
Zudem habe ich festgestellt, dass die Datei als Endung ".xls" hat.
Beim Öffnen mit Excel erscheint die Warnung:
"Das Dateiformat und die Dateierweiterung von 'dataView212_1.xls'
passen nicht zueinander. Möglicherweise ist die Datei beschädigt
oder nicht sicher. Sie sollten sie nicht öffnen, wenn Sie ihrer Quelle
nicht vertrauen. Möchten Sie die Datei trotzdem öffnen?"
Das scheint daran zu liegen, dass die Datei ein xml-DAtei ist.
Bin ratlos.
Benutzeravatar
__blackjack__
User
Beiträge: 8699
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Donnerstag 10. Dezember 2020, 15:48

@tmessers: Warum muss es denn die Exceldatei sein? CSV gibt's da doch auch.

Und mir ist noch nicht wirklich klar was eigentlich die Frage ist? Welcher Pfad? Das musst Du doch wissen unter welchem Pfad Du die Datei gespeichert hast‽
long long ago; /* in a galaxy far far away */
Jankie
User
Beiträge: 592
Registriert: Mittwoch 26. September 2018, 14:06

Donnerstag 10. Dezember 2020, 15:48

Ich würde mir die Daten nicht über das Excel herunterladen, sondern direkt von der Seite Scrapen und dann in ein Dictionary packen:

Code: Alles auswählen

from bs4 import BeautifulSoup
import requests
import pandas as pd

HEADERS = {"User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0"}

def main():
    url = "http://www.gesundheitsatlas-bw.de/dataviews/tabular?viewId=212&geoId=1&subsetId="
    page = requests.get(url, headers=HEADERS)
    soup = BeautifulSoup(page.content, "html.parser")
    table = soup.find('table',{'class':'dataViewTable sortable'}).find('tbody')
    rows = table.find_all('tr')
    data = {}
    for row in rows:
        data[row.find('th',{'class':'row'}).get_text().split()[0]] = row.find('td',{'class':'ar'}).get_text()
    print(data)
    #wenn du doch alles in einem DataFrame willst:
    data_frame = pd.DataFrame.from_dict(data.items()).rename(columns={0: "City", 1: "Value"})
    print(data_frame)

if __name__ == "__main__":
    main()
Zuletzt geändert von Jankie am Donnerstag 10. Dezember 2020, 15:58, insgesamt 1-mal geändert.
Benutzeravatar
__blackjack__
User
Beiträge: 8699
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Donnerstag 10. Dezember 2020, 15:58

@Jankie: Warum denn *das*? Die Daten werden schon in sinnvoll verarbeitbaren Formaten angeboten und Du kratzt das aus dem HTML das sich jederzeit ändern kann‽
long long ago; /* in a galaxy far far away */
tmessers
User
Beiträge: 28
Registriert: Dienstag 30. Oktober 2018, 21:08

Donnerstag 10. Dezember 2020, 16:16

@Jankie: Das ist ein tolle Lösung, die kann ich in anderen Fällen benutzen. Danke dafür.
Im konkreten Fall kann ich auf der Webseite mit dem Button "Alle hinzufügen + " noch den täglchen Verlauf anzeigen lassen.
Diese Daten benötige ich.
Und genau diesen zeilichen Verlauf kann ich in der Excel-Datei aufbereiten lassen.
Lässt sich der täglich Verlauf auch scrapen?

@_blackjack_: Die Veränderung der Daten ist im konkreten Fall nicht entscheidend.
tmessers
User
Beiträge: 28
Registriert: Dienstag 30. Oktober 2018, 21:08

Donnerstag 10. Dezember 2020, 16:44

@_blackjack_: Sorry, ich hatte Deine erste Nachricht nicht gelesen.
Mit Pfad meine ich die URL den Ort, wo die Excel-DAtei im Web liegt.
In einem anderen Projekt nutze ich folgenden Code:
df =pd.read_excel('https://sozialministerium.baden-wuertte ... le-BW.xlsx', sheet_name=0, header=6)
HIer ist die URL klar finde ich. Aber wie lautet die URL für die Excel-Datei in meinem neuen Projekt?
Benutzeravatar
__blackjack__
User
Beiträge: 8699
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Donnerstag 10. Dezember 2020, 17:18

@tmessers: Die hast Du doch in Deinem Beitrag selbst angegeben‽
long long ago; /* in a galaxy far far away */
Sirius3
User
Beiträge: 14558
Registriert: Sonntag 21. Oktober 2012, 17:20

Donnerstag 10. Dezember 2020, 17:31

@__blackjack__: das Problem ist, dass die `instances` sich nicht vorhersehbar ändern. http://www.gesundheitsatlas-bw.de/data/csv?viewId=212&geoId=1&subsetId=&instances=13552
Man müßte also diese IDs doch aus der Hauptseite herausparsen.
tmessers
User
Beiträge: 28
Registriert: Dienstag 30. Oktober 2018, 21:08

Donnerstag 10. Dezember 2020, 18:09

__blackjack__ hat geschrieben:
Donnerstag 10. Dezember 2020, 17:18
@tmessers: Die hast Du doch in Deinem Beitrag selbst angegeben‽
Das ist eine andere URL
tmessers
User
Beiträge: 28
Registriert: Dienstag 30. Oktober 2018, 21:08

Montag 14. Dezember 2020, 09:51

Ich habe jetzt folgende Lösung gebastelt.
Ich schreibe die Daten in ein Excel-File und lese dieses bei jedem Programmdurchlauf
aus. So bekomme ich auch eine Zeitreihe.

Der Code lautet:

Code: Alles auswählen

from bs4 import BeautifulSoup
import requests
import pandas as pd
import datetime
import openpyxl
from pandas import DataFrame

#Hilfe von "Jankie"
#___________________
HEADERS = {"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:44.0) Gecko/20100101 Firefox/44.0"}


def main():
    aktuelles_datum = datetime.datetime.now()
    aktuelles_datum = aktuelles_datum.strftime( "%d.%m." )
    print( aktuelles_datum )
    url = "http://www.gesundheitsatlas-bw.de/dataviews/tabular?viewId=212&geoId=1&subsetId="
    page = requests.get( url, headers=HEADERS )
    soup = BeautifulSoup( page.content, "html.parser" )
    table = soup.find( 'table', {'class': 'dataViewTable sortable'} ).find( 'tbody' )
    rows = table.find_all( 'tr' )
    data = {}
    for row in rows:
        data[row.find( 'th', {'class': 'row'} ).get_text().split()[0]] = row.find( 'td', {'class': 'ar'} ).get_text()
    # print ( data )
    # wenn du doch alles in einem DataFrame willst:
    df = pd.DataFrame.from_dict( data.items() ).rename( columns={0: "Stadt", 1: aktuelles_datum} )
    # print ( data_frame )
    #______________
    df_neu = df.loc[[12, 14, 22, 23, 26, 27], ['Stadt', aktuelles_datum]]
    # print ( data_frame_neu )
    df_neu = df_neu.set_index( 'Stadt' )
    print( df_neu )
    # data_frame_neu.to_excel("output.xlsx")
    df_alt = pd.read_excel( 'output.xlsx', index_col=0, header=0 )
    print( df_alt )
    # Abfrage ob Spalte mit aktuellem Datum bereits vorhanden ist .
    # Wenn ja, wird die Spalte gelöscht
    print (list( df_alt ))
    namen = list( df_alt )
    for i in namen:
        if aktuelles_datum in i:
            del df_alt[aktuelles_datum]
            print( 'Datum war bereits vorhanden und wurde gelöscht.' )
    # print( df_neu )
    df_aktuell: DataFrame = df_alt.join( df_neu )
    print( df_aktuell )
    df_aktuell.to_excel( "output.xlsx" )
    print ('Datei wurde geschrieben.')


if __name__ == "__main__":
    main()


Wie kann der Code noch verbessert werden?
Danke für Eure Hilfe.
tmessers
User
Beiträge: 28
Registriert: Dienstag 30. Oktober 2018, 21:08

Montag 14. Dezember 2020, 10:01

Ich habe noch eine weitere Frage zum auslesen aus Webseiten.
Unter der url
https://geodes.santepubliquefrance.fr/# ... &view=map2
ist beim Aufruf der Seite eine Kartenansicht sichtbar.
Es gibt eine weitere Ansicht, die mit den Button "Tableau" visualisiert werden kann. Die url ändert sich dabei nicht.
Wie kann ich diese Ansicht ansteuern und mit dem Code von Jankie auslesen?
Benutzeravatar
sparrow
User
Beiträge: 2703
Registriert: Freitag 17. April 2009, 10:28

Montag 14. Dezember 2020, 10:10

Gar nicht. Dazu musst du verstehen, wie Webseiten funktionieren.
Eine Seite kann "statisch" sein, dann kannst du die die wie oben beschrieben herunterladen. Es kann aber auch sein, dass die Webseite Java-Script verwendet um Daten nachzuladen, darzustellen, etc. Das Javascript wird normalerweise vom Browser ausgeführt.

Entweder musst du die Webseite analysieren und schauen, welche Aufrufe dein Browser beim dem Besuch durch Javascript ausführt und versuchen, die selbst nachzubauen - oder du versuchst einen Browser fernzusteuern. Stichwort "Selenium".

Viel Erfolg.
tmessers
User
Beiträge: 28
Registriert: Dienstag 30. Oktober 2018, 21:08

Montag 14. Dezember 2020, 23:28

@sparrow: Danke für Deine Antwort

Ich werde mich mit Selenium beschäftigen.
BIs dahin werde ich für dieses Projekt einen anderen Weg suchen.
Ich bin im Netz auf .csv Dateien gestoßen, die die Daten enthalten die ich benötige.
Allderdings ändert sich die url regelmäßig, folgt aber einem Muster. Dieses Muster
könnte ich mir gggfs. zu nutze mache:

Beispiele
Daten für 14.12.2020:
'https://static.data.gouv.fr/resources/i ... -19h25.csv'
Daten für 13.12.2020
'https://static.data.gouv.fr/resources/i ... -19h25.csv'

Meine Idee ist die sich ändernden Teilzeichenketten mit Variablen und mit Platzhaltern zu ersetzen
Etwa so:
'https://static.data.gouv.fr/resources/i ... metropole/[aktuelles Datum im Format yyyymmdd-][Platzhalter]/sg-metro-opendata-[aktuelles Datum im Format yyyy-mm-dd-[Platzhalter].csv'

Ist das praktikabel und wenn ja, wie sieht der Platzhalter aus?
Antworten