Da die Umrechnungskurse sich ständig ändern ist es sinnvoll diese von einem Service Tagesaktuell zu laden. Wir erzeugen uns also eine kleine Funktion welche von einer Schnittstelle im Internet diese Kurse läd.
Wechselkurse vom deutschen Zoll laden
Auf der Internetseite vom deutschen Zoll findest du eine Schnittstelle welche dir Wechselkurse zu Währungen anbietet. Diese Schnittstelle liefert dir die Werte im XML oder CSV Format. Beide Formate können wir mit Python sehr gut auswerten und das wollen wir auch tun. Eine ausführliche Liste mit den Währungen findest du unter https://www.zoll.de/SiteGlobals/Forms/KursSuche/KurseSuche_Formular_NotierteWaehrung.html.
Im nachfolgenden möchte ich dir zeigen wie du das bestehende Projekt aus dem Beitrag Python Flask – einen Währungsrechner programmieren um diese Funktion erweiterst.
Aufbau der URL für den Abruf der Daten
Die Daten werden recht einfach mit einer URL und passenden Parameter abgerufen wobei wir nur maximal 4 Werte ändern bzw. anpassen müssen.
In meinem Beispiel möchte ich die Daten für die Währung US-Dollar abrufen.
http://www.zoll.de/SiteGlobals/Functions/Kurse/KursExport.xml?view=xmlexportkursesearchresultZOLLWeb&kursart=1&iso2code2=US&startdatum_tag2=01&startdatum_monat2=4&startdatum_jahr
2=2021&enddatum_tag2=30&enddatum_monat2=4&enddatum_jahr2=2021&sort=asc&spalte=gueltigkeit
folgende Parameter passen wir in der URL an:
- iso2code2 – die Währung,
- startdatum_tag2 – der erste Tag,
- startdatum_monat2 – der Monat,
- startdatum_jahr2 – das Jahr,
- enddatum_tag2 – der letzte Tag,
- enddatum_monat2 – der Monat,
- enddatum_jahr2 – das Jahr
Im oben gezeigen Beispiel lade ich die Daten für den US-Dollar aus dem Monat April 2021. Als Ergebnis dieser Abfrage erhalten wir eine kleine XML Datei mit einem Kurswert.
<kurse>
<kurs id="240775">
<land>Vereinigte Staaten</land>
<iso2>US</iso2>
<kurswert>1,1825</kurswert>
<iso3>USD</iso3>
<startdatum>01.04.2021</startdatum>
<enddatum>30.04.2021</enddatum>
</kurs>
</kurse>
Benötigte Bibliotheken / Module
Damit wir Daten aus dem Internet abrufen und auswerten können benötigen wir drei zusätzliche Module. Zum einen das Modul requests mit welchen man ganze Seiteninhalte laden kann, die Klasse BeautifulSoup aus dem Modul bs4 zum parsen der geladeten Daten und das Modul lxml welches unseren XML Parser bereitstellt. (Per default kann BeautifulSoup „nur“ HTML Datein parsen.)
Diese drei Module fügen wir in die Datei requirements.txt ein.
Flask==1.1.2
Jinja2==2.10.1
requests==0.11.1
beautifulsoup4==4.9.3
lxml==4.6.3
Auf der Kommandozeile werden die benötigten Module mit dem Befehl:
pip install -r requirements.txt
installiert.
Da ich die Module bereits installiert hatte brauchte nichts zusätzlich geladen werden und es konnten die Daten aus dem Cache geladen werden.
erweitern des bestehenden Quellcodes
Da ich in diesem Beitrag auf ein bestehendes Projekt aufsetze möchte ich dir gerne zeigen wie du das Projekt aus dem GitHub Repository StefanDraeger / PyCurrencyCalulator erweitern kannst.
Als Entwicklungsumgebung nutze ich Eclipse in der Version 2020-12 mit dem Plugin PyDev. Du kannst jedoch auch eine andere oder sogar einen einfachen Editor nutzen.
Schritt 1 – importieren der Module
Da wir bereits die Module geladen haben müssen wir diese nun in den Quellcode importieren.
import calendar import requests from bs4 import BeautifulSoup import lxml import datetime
Das Modul calendar und datetime benötigen wir später für das ermitteln des aktuellen Monats und des Jahres für das abrufen der Daten.
Schritt 2 – ermitteln des Zeitspanne
Wie bereits oben gezeigt nutzen wir eine URL in welche die Zeitspanne für das laden der Daten eingetragen wird. Diese Zeitspanne müssen wir zunächst ermitteln. (Unser späteres Artefakt kann ja auf einem Server ohne Unterbrechung laufen.)
Für die spätere Nutzung der Zeitspanne in unserer Oberfläche speichern wir diese Datenals globale Variable.
currentYear = 0 currentMonth = 0 @app.route('/') def start(): global currentYear global currentMonth currentYear = datetime.date.today().year currentMonth = datetime.date.today().month ....
Zusätzlich zum Startdatum benötigen wir noch das Enddatum das setzt sich aus dem aktuellen Monat sowie dem Jahr zusammen und natürlich den letzten Tag des Monats. Da es jedoch jeder Monat nicht gleich lang ist und das Schaltjahr auch noch mit einfließt müssen wir uns diesen letzten Tag „irgendwie“ berechnen oder aber wir nutzen eine passende Funktion.
max_day_in_month = calendar.monthrange(jahr,monat)[1]
Die Funktion „monthrange“ aus der Klasse calendar liefert ein Tupel, wobei der erste Wert der Wochentag und der zweite die Länge des Monats ist. In unserem Fall interessiert uns nur der letzte Wert und wir greifen gleich auf diesen zu.
Da wir aber das Datum auch in der Oberfläche anzeigen lassen wollen setzten wir uns diesen zusammen und speichern uns das Ergebnis als lokale Variable.
@app.route('/') def start(): ... currentDateStr = getFormatedDate(currentMonth, currentYear) ... def getFormatedDate(month, year): date = "01." if(month< 10): date = date + "0" date = date + str(month)+"." +str(year) return date
Schritt 3 – zusammenführen der Daten für die URL
Im dritten Schritt wollen wir nun die bereits ermittelten Daten für die URL zusammenfügen.
Da die Daten der Zeitspanne als Zahlen vorliegen müssen wir diese jeweils mit der Funktion „str()“ in eine Zeichenkette umwandeln.
url = "http://www.zoll.de/SiteGlobals/Functions/Kurse/KursExport.xml?"\ +"view=xmlexportkursesearchresultZOLLWeb&kursart=1&iso2code2="+currency\ +"&startdatum_tag2=01&startdatum_monat2="+str(monat)+"&startdatum_jahr2="+str(jahr)\ +"&enddatum_tag2="+str(max_day_in_month)+"&enddatum_monat2="+str(monat)+"&enddatum_jahr2="\ +str(jahr)+"&sort=asc&spalte=gueltigkeit"
Der Backslash hinter den Zeilen wird nur benötigt wenn du wie ich die URL zur besseren Lesbarkeit umbrechen möchtest!
Schritt 4 – laden und parsen der Daten
Da wir die beiden Module requests und bs4 zum laden und parsen verwenden ist der Code recht übersichtlich. Diese beiden mächtigen Module erledigen mit wenigen Funktionsaufrufen die arbeit für uns.
... r = requests.get(url) document = BeautifulSoup(r.content, "lxml") return float(document.find('kurswert').text.replace(",","."))
Es fehlen hier noch einpaar Prüfungen ob der Status des Aufrufes mit „requests.get“ auch einen gültigen Inhalt geliefert hat (HTTP Status 200).
Des Weiteren gehen wir davon aus dass, das XML korrekt geladen wurde. Wenn zbsp. eine fehlerhafte Währungsart übergeben wurde ist das Ergebnis leer und es würde in diesem Fall eine Exception auftreten.
Wir gehen jedoch davon aus das der Service immer verfügbar ist und die Währungsart korrekt übergeben wird.
Schritt 5 – umrechnen von US-Dollar in Euro
Die Schnittstelle vom deutschen Zoll bietet nur die Währungsumrechnung von Euro in US-Dollar aber nicht anders herum. Aber dieses können wir recht einfach selber lösen.
euro = round(1/usDollar,4)
Die Funktion round kürzt dabei unser Ergbnis auf 4 Nachkommastellen.
Schritt 6 – speichern der Umrechnungskurse im Dictionary
Die Umrechnungskurse von Euro in US-Dollar und andersherum wollen wir nun in unserem Dictonary speichern.
currencyConversion = { "EUR-USD":1.1916, "USD-EUR":0.8392, "date":"-undefined-" } @app.route('/') def start(): ... currentDateStr = getFormatedDate(currentMonth, currentYear) usDollar = loadDataFromCustoms(currencys["USD"]["iso2code"], currentMonth, currentYear) euro = round(1/usDollar,4) currencyConversion["EUR-USD"] = usDollar currencyConversion["USD-EUR"] = euro currencyConversion["date"] = currentDateStr ...
Schritt 7 – anzeigen der Umrechnunskurse in der Oberfläche
Da wir die ermittelten Daten der Umrechnungskurse in einem Dictionary gespeichert haben übergeben wir dieses an unsere HTML Oberfläche und holen uns dort die entsprechenden Werte heraus.
Zunächst übergeben wir diesen zusätzlichen Parameter an das Template.
return render_template("template.html", umrechnunskurse=currencyConversion , srcValue=srcValue, srcCurrencyBlock=srcCurrency, destCurrencyBlock=destCurrency)
In der Datei template.html wir ein zusätzlicher Block implementiert wo wir die Umrechnungskurse anzeigen lassen wollen.
<div> <h2>Umrechnungskurse</h2> <p>EURO in US-Dollar - {{ umrechnunskurse["EUR-USD"] }}</p> <p>US-Dollar in EURO - {{ umrechnunskurse["USD-EUR"] }}</p> <p>Stand: {{ umrechnunskurse["date"] }}</p> </div>
das fertige Programm zum Download
Auf meinem Github Repository findest du das Release 0.3 mit der zusätzlichen Funktion um die Umrechnungskurse vom deutschen Zoll zu beziehen.