Hallo liebe Python-Gemeinde,
ich habe ein Frage zu einem Projekt.
Unter
https://www.baden-wuerttemberg.de/de/se ... rttemberg/
liegt ein Karte. In dieser sind Zahlenwerte eingetragen. Ich möchte bestimmte Zahlenwerte täglich auslesen und in ein json-file schreiben. Mit Pandas erzeuge ich dann ein DataFrame und erzeuge mit matplotlib die grafische Darstellung.
Ich habe versucht mit BeautifulSoup die Zahlenwerte zu finden, komme da aber nicht weiter.
Weiß jemand Rat?
Danke im Voraus für Eure Unterstützung.
Werte aus Homepage auslesen
Ich sehe da keine Karte. Darum kann man nur raten.
Ein Klassiker ist die Verwendung von JavaScript zum nachladen. Wenn das der Fall ist, kannst du im Browser debugger versuchen die requests zu identifizieren. Und die dann direkt nutzen. Oder zur Not selenium einsetzen.
Ein Klassiker ist die Verwendung von JavaScript zum nachladen. Wenn das der Fall ist, kannst du im Browser debugger versuchen die requests zu identifizieren. Und die dann direkt nutzen. Oder zur Not selenium einsetzen.
- __blackjack__
- User
- Beiträge: 14052
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
Das Bild ist ein JPEG und die Zahlen auf der Karte sind im Bild. Das wirst Du da nicht so wirklich einfach raus bekommen.
Nach ein bisschen unmotiviertem rumklicken auf den Seiten, habe ich auf dieser Seite: https://sozialministerium.baden-wuertte ... rttemberg/ eine Excel-Datei entdeckt. Vielleicht ist das ja was für Dich.
Nach ein bisschen unmotiviertem rumklicken auf den Seiten, habe ich auf dieser Seite: https://sozialministerium.baden-wuertte ... rttemberg/ eine Excel-Datei entdeckt. Vielleicht ist das ja was für Dich.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Danke für den Tipp.
Der war sehr gut.
Ich habe den folgenden Code geschrieben,
der meinen Zwecke erfüllt.
Was lässt sich aus Eurer Sicht verbessern?
Der war sehr gut.
Ich habe den folgenden Code geschrieben,
der meinen Zwecke erfüllt.
Code: Alles auswählen
import pandas as pd
import matplotlib.pyplot as plt
import time
from datetime import date
import dateutil
df =pd.read_excel('https://sozialministerium.baden-wuerttemberg.de/fileadmin/redaktion/m-sm/intern/downloads/Downloads_Gesundheitsschutz/Tabelle_Coronavirus-Faelle-BW.xlsx', sheet_name=0, header=6)
#print(df)
#Auswahl der Zeilen, die Berücksichtigt werden sollen
df_auswahl=df.loc[[10,5,1,26,29],:]
#Transponieren der Spalten
df_auswahl=df_auswahl.T
#Erste Zeile des DataFrame löschen
df_auswahl.drop(['Unnamed: 0'],inplace=True)
df_auswahl.columns = ['Freiburg','Breisg.-Hochschw.','Baden-Baden','Ortenau','Rastatt']
#print(df_auswahl)
#——-Dialog: Zeitraum auswählen über Datum
#Letzen Datumswert ermitteln
erst_datum=df_auswahl.index[-1]
Frage=input('Wollen Sie den Zeitraum eingrenzen? j/n: /n Erstes Datum ist %s' %erst_datum)
if Frage == 'j':
monat=input('Geben Sie den Monat ein. Format XX: ')
tag=input('Geben Sie einen Tag ein. Format XX: ')
datum=('2020-%s-%s' %(monat,tag))
else:
datum=str(erst_datum)
#DataFrame in Abhängigkeit von datum erstellen
df_neu= df_auswahl[df_auswahl.index > dateutil.parser.parse(datum)]
#print(df_neu)
#——-Werte für annotate ermitteln
wert_fre=int(df_neu.at[df_neu.index[0],df_neu.columns[0]])
#print(wert_fre)
wert_brh=int(df_neu.at[df_neu.index[0],df_neu.columns[1]])
wert_bad=int(df_neu.at[df_neu.index[0],df_neu.columns[2]])
wert_ort=int(df_neu.at[df_neu.index[0],df_neu.columns[3]])
wert_ras=int(df_neu.at[df_neu.index[0],df_neu.columns[4]])
#aktuelles Datum im DataFrame-Index ermitteln
akt_datum=df_neu.index[0]
#print(akt_datum)
#———Erstellung des Diagramms mit matplotlib
#Festlegung des Standes
stand=date.today()
#Plot erstellen
df_neu.plot(marker='.')
plt.xticks(rotation=30)
plt.grid(True)
plt.title('Coronafälle Stand: %s' %stand)
plt.gcf().autofmt_xdate()
plt.annotate(str(wert_fre),xy=(akt_datum,wert_fre),color='blue')
plt.annotate(str(wert_brh),xy=(akt_datum,wert_brh),color='orange')
plt.annotate(str(wert_bad),xy=(akt_datum,wert_bad),color='green')
plt.annotate(str(wert_ort),xy=(akt_datum,wert_ort),color='red')
plt.annotate(str(wert_ras),xy=(akt_datum,wert_ras),color='purple')
plt.xlabel('Datum')
plt.ylabel('Fälle')
plt.show()
dateiname= ('%s Corona-BW.pdf' %stand)
plt.savefig(dateiname)
Danke für den Tipp.
Der war sehr gut.
Ich habe den folgenden Code geschrieben,
der meinen Zwecke erfüllt.
Was lässt sich aus Eurer Sicht verbessern?
Der war sehr gut.
Ich habe den folgenden Code geschrieben,
der meinen Zwecke erfüllt.
Code: Alles auswählen
import pandas as pd
import matplotlib.pyplot as plt
import time
from datetime import date
import dateutil
df =pd.read_excel('https://sozialministerium.baden-wuerttemberg.de/fileadmin/redaktion/m-sm/intern/downloads/Downloads_Gesundheitsschutz/Tabelle_Coronavirus-Faelle-BW.xlsx', sheet_name=0, header=6)
#print(df)
#Auswahl der Zeilen, die Berücksichtigt werden sollen
df_auswahl=df.loc[[10,5,1,26,29],:]
#Transponieren der Spalten
df_auswahl=df_auswahl.T
#Erste Zeile des DataFrame löschen
df_auswahl.drop(['Unnamed: 0'],inplace=True)
df_auswahl.columns = ['Freiburg','Breisg.-Hochschw.','Baden-Baden','Ortenau','Rastatt']
#print(df_auswahl)
#——-Dialog: Zeitraum auswählen über Datum
#Letzen Datumswert ermitteln
erst_datum=df_auswahl.index[-1]
Frage=input('Wollen Sie den Zeitraum eingrenzen? j/n: /n Erstes Datum ist %s' %erst_datum)
if Frage == 'j':
monat=input('Geben Sie den Monat ein. Format XX: ')
tag=input('Geben Sie einen Tag ein. Format XX: ')
datum=('2020-%s-%s' %(monat,tag))
else:
datum=str(erst_datum)
#DataFrame in Abhängigkeit von datum erstellen
df_neu= df_auswahl[df_auswahl.index > dateutil.parser.parse(datum)]
#print(df_neu)
#——-Werte für annotate ermitteln
wert_fre=int(df_neu.at[df_neu.index[0],df_neu.columns[0]])
#print(wert_fre)
wert_brh=int(df_neu.at[df_neu.index[0],df_neu.columns[1]])
wert_bad=int(df_neu.at[df_neu.index[0],df_neu.columns[2]])
wert_ort=int(df_neu.at[df_neu.index[0],df_neu.columns[3]])
wert_ras=int(df_neu.at[df_neu.index[0],df_neu.columns[4]])
#aktuelles Datum im DataFrame-Index ermitteln
akt_datum=df_neu.index[0]
#print(akt_datum)
#———Erstellung des Diagramms mit matplotlib
#Festlegung des Standes
stand=date.today()
#Plot erstellen
df_neu.plot(marker='.')
plt.xticks(rotation=30)
plt.grid(True)
plt.title('Coronafälle Stand: %s' %stand)
plt.gcf().autofmt_xdate()
plt.annotate(str(wert_fre),xy=(akt_datum,wert_fre),color='blue')
plt.annotate(str(wert_brh),xy=(akt_datum,wert_brh),color='orange')
plt.annotate(str(wert_bad),xy=(akt_datum,wert_bad),color='green')
plt.annotate(str(wert_ort),xy=(akt_datum,wert_ort),color='red')
plt.annotate(str(wert_ras),xy=(akt_datum,wert_ras),color='purple')
plt.xlabel('Datum')
plt.ylabel('Fälle')
plt.show()
dateiname= ('%s Corona-BW.pdf' %stand)
plt.savefig(dateiname)
- __blackjack__
- User
- Beiträge: 14052
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@tmessers: Anmerkungen zum Quelltext:
`time` wird importiert, aber nicht verwendet.
Eingerückt wird in Python vier Leerzeichen pro Ebene, nicht zwei.
Nach Kommas und um binäre Operatoren erhöhen Leerzeichen die Lesbarkeit. Den ``%``-Operator hast Du anscheinend immer an den zweiten Operanden gesetzt, und bei einfachen Zuweisungen immer unnötige Klammern um den Ausdruck gesetzt‽
``%`` würde ich in neuem Code auch nicht mehr zur Zeichenkettenformatierung verwenden wenn es dafür nicht einen guten Grund gibt. Es gibt die `format()`-Methode und ab Python 3.6 f-Zeichenkettenliterale.
Die Auswahl der Zeilen nach Nummern wäre mir nicht robust genug. Ich würde da die erste Spalte zum Index machen und über die Namen zugreifen.
Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase). `Frage` würde also klein geschrieben. Aber es ist gar keine Frage sondern eine Antwort.
Das Datum erst in eine Zeichenkette zu wandeln nur um es danach zu parsen ist unsinnig. Stattdessen sollte man einfach aus der Benutzereingabe gleich ein `datetime.date`-Objekt oder ein `pandas.Timestamp`-Objekt erstellen.
Namen sollten keine kryptischen Abkürzungen enthalten. Die ganzen "wert_???"-Namen mit den dreibuchstabigen Stadt-/Landkreisabkürzungen sind schlecht. Das sollten auch gar keine einzelnen Namen sein, denn man kann die erste Zeile einfach an den Namen `aktuelle_fallzahlen` binden und auch Pandas gleich zum Umwandeln nach `int` verwenden:
Für die `annotate()`-Aufrufe kann man dann eine Schleife über dieser Werte und die dazugehörigen Farben schreiben.
Apropos Farben: Die sollten da nicht so fest kodiert im Quelltext stehen, denn die hängen vom Farbschema ab. Wenn man die aus dem Plot von den Linien abfragt, ist man vom Farbschema unabhängig und bekommt dort immer die passenden Farben. Und man ist dann auch von der Anzahl der ausgewählten Stadt-/Landkreise unabhängig und kann ganz einfach welche hinzufügen oder weglassen, ohne den restlichen Code ändern zu müssen.
`time` wird importiert, aber nicht verwendet.
Eingerückt wird in Python vier Leerzeichen pro Ebene, nicht zwei.
Nach Kommas und um binäre Operatoren erhöhen Leerzeichen die Lesbarkeit. Den ``%``-Operator hast Du anscheinend immer an den zweiten Operanden gesetzt, und bei einfachen Zuweisungen immer unnötige Klammern um den Ausdruck gesetzt‽
``%`` würde ich in neuem Code auch nicht mehr zur Zeichenkettenformatierung verwenden wenn es dafür nicht einen guten Grund gibt. Es gibt die `format()`-Methode und ab Python 3.6 f-Zeichenkettenliterale.
Die Auswahl der Zeilen nach Nummern wäre mir nicht robust genug. Ich würde da die erste Spalte zum Index machen und über die Namen zugreifen.
Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase). `Frage` würde also klein geschrieben. Aber es ist gar keine Frage sondern eine Antwort.
Das Datum erst in eine Zeichenkette zu wandeln nur um es danach zu parsen ist unsinnig. Stattdessen sollte man einfach aus der Benutzereingabe gleich ein `datetime.date`-Objekt oder ein `pandas.Timestamp`-Objekt erstellen.
Namen sollten keine kryptischen Abkürzungen enthalten. Die ganzen "wert_???"-Namen mit den dreibuchstabigen Stadt-/Landkreisabkürzungen sind schlecht. Das sollten auch gar keine einzelnen Namen sein, denn man kann die erste Zeile einfach an den Namen `aktuelle_fallzahlen` binden und auch Pandas gleich zum Umwandeln nach `int` verwenden:
Code: Alles auswählen
In [66]: df.iloc[0].astype(int)
Out[66]:
Freiburg 921
Breisg.-Hochschw. 1019
Baden-Baden 164
Ortenau 936
Rastatt 473
Name: 2020-04-22 00:00:00, dtype: int64
Apropos Farben: Die sollten da nicht so fest kodiert im Quelltext stehen, denn die hängen vom Farbschema ab. Wenn man die aus dem Plot von den Linien abfragt, ist man vom Farbschema unabhängig und bekommt dort immer die passenden Farben. Und man ist dann auch von der Anzahl der ausgewählten Stadt-/Landkreise unabhängig und kann ganz einfach welche hinzufügen oder weglassen, ohne den restlichen Code ändern zu müssen.
Code: Alles auswählen
#!/usr/bin/env python3
from datetime import date as Date
import matplotlib.pyplot as plt
import pandas as pd
EXCEL_FILE_URL = (
"https://sozialministerium.baden-wuerttemberg.de/"
"fileadmin/redaktion/m-sm/intern/downloads/Downloads_Gesundheitsschutz/"
"Tabelle_Coronavirus-Faelle-BW.xlsx"
)
def main():
#
# Paare: (Bezeichnung in Quelle, kürzere Bezeichnung für den Plot).
#
stadt_und_landkreise = [
("Freiburg im Breisgau (Stadtkreis)", "Freiburg"),
("Breisgau-Hochschwarzwald", "Breisg.-Hochschw."),
("Baden-Baden (Stadtkreis)", "Baden-Baden"),
("Ortenaukreis", "Ortenau"),
("Rastatt", "Rastatt"),
]
df_auswahl = (
pd.read_excel(EXCEL_FILE_URL, header=6, index_col=0)
.loc[[bezeichnung for bezeichnung, _ in stadt_und_landkreise], :]
.transpose()
)
df_auswahl.columns = [
kurz_bezeichnung for _, kurz_bezeichnung in stadt_und_landkreise
]
datum = df_auswahl.index[-1]
antwort = input(
f"Wollen Sie den Zeitraum eingrenzen? j/n: /n"
f" Erstes Datum ist {datum}"
)
if antwort == "j":
monat = int(input("Geben Sie den Monat ein: "))
tag = int(input("Geben Sie einen Tag ein: "))
datum = pd.Timestamp(year=2020, month=monat, day=tag)
df_plot_auswahl = df_auswahl[df_auswahl.index > datum]
aktuelle_fallzahlen = df_plot_auswahl.iloc[0].astype(int)
aktuelles_datum = aktuelle_fallzahlen.name
stand = Date.today()
plot = df_plot_auswahl.plot(
title=f"Coronafälle Stand: {stand}", grid=True, rot=30, marker="."
)
plt.gcf().autofmt_xdate()
plt.xlabel("Datum")
plt.ylabel("Fälle")
for fallzahl, farbe in zip(
aktuelle_fallzahlen, (line.get_color() for line in plot.get_lines())
):
plt.annotate(
str(fallzahl), xy=(aktuelles_datum, fallzahl), color=farbe
)
plt.show()
plt.savefig(f"{stand} Corona-BW.pdf")
if __name__ == "__main__":
main()
“Vir, intelligence has nothing to do with politics!” — Londo Mollari