Archive for the ‘Programmierung’ Category.

Adressen zerlegen mit Python

Ich bin kürzlich auf die Herausforderung gestoßen, verschiedene Adresstypen aufzusplitten. Gegeben war immer die Straße und die Hausnummer, allerdings in verschiedenen länderspezifischen Variationen.

Hier eine Datei Datensatz.txt mit den Straßen:

Thanelstr. 46
Sieglinde-Briemer-Straße 716
Rennerstr. 542a
34, Rue de la Chanson
456 Market Square
Auf der Burg
Auf der Burg 234
90211 Melrost Place, Apt. 1

Hinweis: Benötigt man größere Mengen an Fake-Adressen, dann leistet die Faker-Bibliothek (https://github.com/joke2k/faker) gute Dienste. Mit dem folgenden Python-Code gelingt der Split in Straße und Hausnummer recht gut:

with open('Datensatz.txt', 'rt', encoding='utf-8') as eingabedatei:
    for zeile in eingabedatei:
 
        if zeile[-1] == '\n':
            zeile = zeile[:-1] # Entferne Zeilenumbruch, falls vorhanden
        gesplittet = zeile.split(' ') # Splitte anhand des Leerzeichens
        print(gesplittet) # gibt die Liste aus
 
        if gesplittet[-1].isdigit() and gesplittet[0].isdigit():
            namensteil = ''
            for i in gesplittet[1:]:
                namensteil = namensteil + " " + i 
            print('Name ist "', namensteil.strip() ,  '", Hausnummer ist ',  gesplittet[0], sep = '')
 
        elif gesplittet[-1][0].isdigit() and gesplittet[-1][-1].isalpha():
            namensteil = ''
            for i in gesplittet[:-1]:
                namensteil = namensteil + " " + i 
            print('Name ist "', namensteil.strip() ,  '", Hausnummer ist ',  gesplittet[-1], sep = '')
 
        elif gesplittet[-1].isdigit():
            namensteil = ''
            for i in gesplittet[:-1]:
                namensteil = namensteil + " " + i 
            print('Name ist "', namensteil.strip() ,  '", Hausnummer ist ',  gesplittet[-1], sep = '')
 
        elif gesplittet[0].isdigit():
            namensteil = ''
            for i in gesplittet[1:]:
                namensteil = namensteil + " " + i 
            print('Name ist "', namensteil.strip() ,  '", Hausnummer ist ',  gesplittet[0], sep = '')            
 
        elif gesplittet[0][0].isdigit() and gesplittet[0][-1] == ',':
            namensteil = ''
            for i in gesplittet[1:]:
                namensteil = namensteil + " " + i 
            print('Name ist "', namensteil.strip() ,  '", Hausnummer ist ',  gesplittet[0][:-1], sep = '')

Ergebnis:

['Thanelstr.', '46']
Name ist "Thanelstr.", Hausnummer ist 46
['Sieglinde-Briemer-Straße', '716']
Name ist "Sieglinde-Briemer-Straße", Hausnummer ist 716
['Rennerstr.', '542a']
Name ist "Rennerstr.", Hausnummer ist 542a
['34,', 'Rue', 'de', 'la', 'Chanson']
Name ist "Rue de la Chanson", Hausnummer ist 34
['456', 'Market', 'Square']
Name ist "Market Square", Hausnummer ist 456
['Auf', 'der', 'Burg']
['Auf', 'der', 'Burg', '234']
Name ist "Auf der Burg", Hausnummer ist 234
['90211', 'Melrost', 'Place,', 'Apt.', '1']
Name ist "Melrost Place, Apt. 1", Hausnummer ist 90211

Die Lösung ist nicht optimal, besser fährt man sicher mit libpostal und seinen Python-Bindings (https://github.com/openvenues/pypostal)

Uwe

Uwe Ziegenhagen mag LaTeX und Python, auch gern in Kombination. Hat Dir dieser Beitrag geholfen und möchtest Du Dich dafür bedanken? Dann unterstütze doch vielleicht die Dingfabrik Köln e.V. mit einem kleinen Beitrag. Details zur Bezahlung findest Du unter Spenden für die Dingfabrik.

More Posts - Website

Mit Python PDFs herunterladen

Mit dem folgenden Python-Skript lassen sich auf einfache Weise alle PDFs von einer Webseite herunterladen.

from bs4 import BeautifulSoup
import urllib.request
import requests
 
url = 'http://irgendeineurl.de'
 
r  = requests.get(url)
data = r.text
soup = BeautifulSoup(data)
 
for link in soup.find_all('a'):
    if link.get('href').endswith('.pdf'):
        urllib.request.urlretrieve(url + link.get('href'), link.get('href'))
        print(url + link.get('href'))

Uwe

Uwe Ziegenhagen mag LaTeX und Python, auch gern in Kombination. Hat Dir dieser Beitrag geholfen und möchtest Du Dich dafür bedanken? Dann unterstütze doch vielleicht die Dingfabrik Köln e.V. mit einem kleinen Beitrag. Details zur Bezahlung findest Du unter Spenden für die Dingfabrik.

More Posts - Website

Ordner anlegen mit Python und Excel

Für das Github-Repository der Vorträge von Dante e.V. Vereinstagungen habe ich heute eine Menge Unterordner nebst entsprechenden README-Dateien anlegen dürfen. Da die manuelle Anlage zu lange gedauert hätte (und Verschwendung wertvoller Lebenszeit bedeutet hätte), habe ich ein kleines Python-Skript genutzt, das sich die Daten aus einer Excel-Datei geholt hat.

Die Excel-Datei Daten.xlsx hatte dabei den folgenden Aufbau:

Mit dem folgenden Skript habe ich pro Jahr jeweils zwei Unterordner angelegt und die README-Datei jeweils mit dem passenden Titel versorgt. Man hätte es noch schöner schreiben können, für einen Quick und Dirty Hack war es aber mehr als ausreichend.

import pandas as pd
import os
 
df = pd.read_excel('Daten.xlsx')
 
for index, row in df.iterrows():
    jahr = str(row['Year'])
 
    f1 = jahr + '-Frühling'
    f2 = jahr + '-Herbst'
    spring = row['Spring']
    autumn = row['Autumn']
 
    try:
        if not os.path.exists(f1):
            os.makedirs(f1)
    except OSError:
        print ('Fehler bei Verzeichnis ' +  directory)
 
    with open(f1+'/README.md', 'wt') as file:
        file.write('# Vorträge der Dante e.V. Frühjahrstagung '+jahr + '\n\n')
        file.write('Datum: \n')
        file.write('Veranstaltungsort: ' + spring +'\n')
 
    try:
        if not os.path.exists(f2):
            os.makedirs(f2)
    except OSError:
        print ('Fehler bei Verzeichnis ' +  directory)
 
 
    with open(f2+'/README.md','wt') as file:
        file.write('# Vorträge der Dante e.V. Herbsttagung '+jahr + '\n\n')
        file.write('Datum: \n')
        file.write('Veranstaltungsort: ' + autumn +'\n')

Uwe

Uwe Ziegenhagen mag LaTeX und Python, auch gern in Kombination. Hat Dir dieser Beitrag geholfen und möchtest Du Dich dafür bedanken? Dann unterstütze doch vielleicht die Dingfabrik Köln e.V. mit einem kleinen Beitrag. Details zur Bezahlung findest Du unter Spenden für die Dingfabrik.

More Posts - Website

Python-Übungsaufgabe: MD5-Hashes

Hier eine Übungsaufgabe, die ich mir heute basierend auf https://www.programmieraufgaben.ch/aufgabe/baeckerei-b-rot/xyikp5d5 ausgedacht habe:

Eine Firma hat sich im Streit von ihrem alten Administrator getrennt und hat jetzt ein Problem. Das Passwort für das Lohnzahlungssystem hatte nur der Admin, man kann es nicht zurücksetzen und sollte es einmal falsch eingegeben werden, werden alle Daten der letzten zehn Jahre gelöscht.

Studentin Susanne, die gerade ein Praktikum bei der Firma macht, findet im Dateisystem des Rechners eine Datei, die einen MD5-Hash vom Passwort enthält. Zusätzlich ist bekannt, dass es sich beim Passwort um (verschiedene Fälle mit steigender Komplexität)

* eine vierstellige Zahl (Hash lautet \texttt{48c8c3963853fff20bd9e8bee9bd4c07})
* eine fünfstellige Zahl (Hash selbst ausdenken) oder
* eine sechsstellige Zahl oder
* einen String aus vier (oder fünf oder sechs) Ziffern und Kleinbuchstaben (super als Hausaufgabe!)

handelt. Schreiben Sie ein Programm, das das Passwort im Klartext auf Basis des MD5-Hash ausgibt.

Für die Bestimmung des MD5-Hash nutzen Sie eine passende Bibliothek, eine Implementierung des Algorithmus ist natürlich nicht notwendig.

Uwe

Uwe Ziegenhagen mag LaTeX und Python, auch gern in Kombination. Hat Dir dieser Beitrag geholfen und möchtest Du Dich dafür bedanken? Dann unterstütze doch vielleicht die Dingfabrik Köln e.V. mit einem kleinen Beitrag. Details zur Bezahlung findest Du unter Spenden für die Dingfabrik.

More Posts - Website

Zwei Aufgabenblätter auf einer Seite mit LaTeX

Für meine Studierenden erstelle ich diverse Übungsblätter, damit das Thema „Python“ etwas anschaulicher wird. Dazu nutze ich ein angepasstes LaTeX-Template, mit dem ich die Seite dupliziere und in verkleinerter Form auf das DIN A4-Blatt bringe.

%!TEX TS-program = Arara
% arara: pdflatex: {shell: yes}
% arara: pdflatex: {shell: yes}
% arara: clean: { extensions: [ log, aux, nav, out, snm, vrb, toc ] }
 
\documentclass[a4paper,ngerman,12pt]{exam} 
 
\usepackage{babel}
\usepackage[a4paper,top=2.5cm,bottom=3cm,left=2.5cm,right=2cm]{geometry}
\usepackage[T1]{fontenc}
\usepackage{booktabs}
\usepackage{graphicx}
\usepackage{csquotes}
\usepackage{paralist}
\usepackage[math]{iwona}
\usepackage{textcomp}
\usepackage{listings}
\usepackage{xcolor}
 
\pointpoints{Punkt}{Punkte}
\bonuspointpoints{Bonuspunkt}{Bonuspunkte}
\renewcommand{\solutiontitle}{\noindent\textbf{Lösung:}\enspace}
 
\chqword{Frage}   
\chpgword{Seite} 
\chpword{Punkte}   
\chbpword{Bonus Punkte} 
\chsword{Erreicht}   
\chtword{Gesamt}
 
\pagestyle{headandfoot}
\runningheadrule
 
%%%%%%%
\definecolor{hellgelb}{rgb}{1,1,0.8}
\definecolor{lightgelb}{rgb}{1,1,0.8}
\definecolor{colKeys}{rgb}{0,0,1}
\definecolor{colIdentifier}{rgb}{0,0,0}
\definecolor{colComments}{rgb}{1,0,0}
\definecolor{colString}{rgb}{0,0.5,0}
 
\usepackage{listings}
\lstset{%
    float=hbp,%
    basicstyle=\ttfamily\footnotesize, %
    identifierstyle=\color{colIdentifier}, %
    keywordstyle=\color{colKeys}, %
    stringstyle=\color{colString}, %
    commentstyle=\color{colComments}, %
    columns=flexible, %
    tabsize=2, %
    frame=single, %
    upquote=true,%
    extendedchars=true, %
    showspaces=false, %
    showstringspaces=false, %
    numbers=left, %
    numberstyle=\tiny, %
    breaklines=true, %
    backgroundcolor=\color{hellgelb}, %
    breakautoindent=true, %
    captionpos=b%
}
 
%%%%%%%%%%%%
\lstset{literate=%
    {Ö}{{\"O}}1
    {Ä}{{\"A}}1
    {Ü}{{\"U}}1
    {ß}{{\ss}}1
    {ü}{{\"u}}1
    {ä}{{\"a}}1
    {ö}{{\"o}}1
    {~}{{\textasciitilde}}1
}
 
 
 
\usepackage{pgfpages}                                 % <— load the package
\usepackage{atbegshi}
 
\newcommand{\twoonone}{% 
  \pgfpagesuselayout{2 on 1}[a4paper,landscape,border shrink=5mm] % <— set options
  % duplicate the content at shipout time
  \AtBeginShipout{%
    \pgfpagesshipoutlogicalpage{1}\copy\AtBeginShipoutBox%
    \pgfpagesshipoutlogicalpage{2}\box\AtBeginShipoutBox%
    \pgfshipoutphysicalpage%
  }}
 
 
 
\firstpageheader{WS~2018/2019}{Skriptsprachenprogrammierung}{Dr.~Uwe Ziegenhagen}
\runningheader{WS~2018/2019}{Skriptsprachenprogrammierung}{Dr.~Uwe Ziegenhagen}
\firstpagefooter{\today}{}{\thepage\,/\,\numpages}
\runningfooter{\today}{Mitte unten}{\thepage\,/\,\numpages}
 
\setlength{\parindent}{0pt}
\setlength{\parskip}{6pt}
 
 
\twoonone % two pages on one
 
\begin{document}
 
\vspace*{0.5cm}
\begin{center}
\huge\bfseries Arbeitsblatt 02: Datentypen
\end{center}
\vspace*{0.5cm}
 
\section*{Aufgaben}
 
\begin{questions}
\question Welche Datentypen kennen Sie in Python?
 
\begin{itemize}
	\item 
	\item 
	\item 
	\item 
	\item 
\end{itemize}
 
\question Erstellen Sie verschiedene Variablen mit unterschiedlichen Datentypen! Führen Sie verschiedene Grundrechenarten mit den Datentypen durch.
 
\question Satz des Pythagoras: Berechnen Sie mittels Python die Hypotenuse eines Dreiecks, dessen Katheten 3 und 4 Zentimeter lang sind. Prüfen Sie die Datentypen der Variablen mittels \texttt{type()} Funktion! Warum gibt es Unterschiede in den Typen?
 
\question Richten Sie einen String beliebiger Länge bei der Ausgabe auf der Kommandozeile rechtsbündig aus! Hinweise: Gehen Sie von einer Zeilenbreite von 60 Zeichen aus. Benutzen Sie die \texttt{len()} Funktion, um die Länge der Zeichenkette zu bestimmen.
 
\question Nutzen Sie die \texttt{int()}, \texttt{float()} und \texttt{str()} Funktion, um verschiedene Datentypen umzuwandeln!
 
\question Hier kommt ein Listing
 
\begin{lstlisting}[language={Python}]
def create_bruch():
    zahlen = list(range(1,13))
    zaehler = random.choice(zahlen)
    zahlen.remove(zaehler)
    nenner = random.choice(zahlen)
    return 1234
\end{lstlisting}
 
\end{questions}
 
\end{document}

Uwe

Uwe Ziegenhagen mag LaTeX und Python, auch gern in Kombination. Hat Dir dieser Beitrag geholfen und möchtest Du Dich dafür bedanken? Dann unterstütze doch vielleicht die Dingfabrik Köln e.V. mit einem kleinen Beitrag. Details zur Bezahlung findest Du unter Spenden für die Dingfabrik.

More Posts - Website

Adressen parsen mit Python und libpostal/pypostal

Beim letzten Treffen der PyCologne habe ich meinen Ansatz vorgestellt, um „Straße Hausnummer“ Kombinationen aus verschiedenen Ländern zu parsen. Jemand in der Gruppe gab mir dann den Hinweis auf libpostal und seine Python-Bindings.

Unter Windows habe ich es nicht zum Laufen bekommen, die Installationsroutine setzt noch diverse Compiler voraus. Unter Linux klappt die Installation, wenn man sich genau an die Anleitung unter https://github.com/openvenues/pypostal hält.

Dann kann man mittels parse_address() die Adressdaten verarbeiten.

(base) uwe@Micro:~$ python
Python 3.7.4 (default, Aug 13 2019, 20:35:49)
[GCC 7.3.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from postal.parser import parse_address
>>> parse_address("Meisenweg 1")
[('meisenweg', 'road'), ('1', 'house_number')]
>>> parse_address("10 Downing Street")
[('10', 'house_number'), ('downing street', 'road')]
>>> parse_address("10, Rue de Pommes Frites")
[('10', 'house_number'), ('rue de pommes frites', 'road')]
>>> parse_address("Am Geldspeicher 1, 12345 Entenhausen")
[('am geldspeicher', 'road'), ('1', 'house_number'), ('12345', 'postcode'), ('entenhausen', 'city')]
>>>

Uwe

Uwe Ziegenhagen mag LaTeX und Python, auch gern in Kombination. Hat Dir dieser Beitrag geholfen und möchtest Du Dich dafür bedanken? Dann unterstütze doch vielleicht die Dingfabrik Köln e.V. mit einem kleinen Beitrag. Details zur Bezahlung findest Du unter Spenden für die Dingfabrik.

More Posts - Website

Vortragsfolien zum Thema „TDD mit Python“

Hier die Folien einer Präsentation, die ich auf den Python-Stammtischen in Düsseldorf und Köln gehalten habe.

PyDDF-TDD-UweZiegenhagen.pdf

Uwe

Uwe Ziegenhagen mag LaTeX und Python, auch gern in Kombination. Hat Dir dieser Beitrag geholfen und möchtest Du Dich dafür bedanken? Dann unterstütze doch vielleicht die Dingfabrik Köln e.V. mit einem kleinen Beitrag. Details zur Bezahlung findest Du unter Spenden für die Dingfabrik.

More Posts - Website

Fake-Adressen in Python erstellen

Für eine Übungsaufgabe meiner Skriptsprachen-Vorlesung an der FOM in Köln benötigte ich eine große Menge an „Straße Hausnummer“ Kombinationen. Mit faker gibt es ein Python-Modul, das nicht nur diese Adressen, sondern auch Namen, E-Mail-Adressen, ISBNs, etc. für diverse Locales schnell erzeugen kann.

Den folgenden Code habe ich benutzt:

from faker import Faker
 
locales = ['de_DE', 'cs_CS', 'nl_NL', 'pl_PL', 'fr_FR', 'dk_DK', 'en_US']
 
with open('musteradressen.txt','wt', encoding='utf-8') as file:
    for i in locales:
        fake = Faker(i)
 
        for j in range(100):
            t = fake.address()
            print(t)
            if '\n' in t:
                t = t[:t.index('\n'):]
            file.write(t + '\n')

Da ich nur die Straßennamen mit Hausnummern benötigte, habe ich jeweils die PLZ und Ortsinformation zusammen mit dem Zeilenumbruch gelöscht.

Händisch wurden dann US-Schiffsangaben und Unit/PO-BOX Angaben gelöscht.

Uwe

Uwe Ziegenhagen mag LaTeX und Python, auch gern in Kombination. Hat Dir dieser Beitrag geholfen und möchtest Du Dich dafür bedanken? Dann unterstütze doch vielleicht die Dingfabrik Köln e.V. mit einem kleinen Beitrag. Details zur Bezahlung findest Du unter Spenden für die Dingfabrik.

More Posts - Website

Und() und Oder() in Excel-Formeln nutzen

Hier ein anschauliches Beispiel für die Nutzung der Und() und Oder() Formel in Excel.

Gesucht werden die Zeilen, in denen Spalte A gleiche Werte aufweist, in Spalte B jedoch nicht.

Die Lösung dafür liegt in einer verschachtelten Und()/Oder() Funktion, schauen wir uns das mal für die Zeile 6 an:

Ich suche die Zeilen, in denen der Wert von Spalte A (also A6) dem Wert der vorigen Zeile (also A5) entspricht UND gleichzeitig der Wert aus Spalte B nicht dem Wert aus der vorigen Zelle entspricht.

Dies resultiert in der Formel: UND(A6=A5;B6<>B5)

Ich muss jedoch nicht nur die vorherige Zeile prüfen, sondern auch die folgende. Analog Prüfung auf die vorherige Zeile ergibt sich: UND(A6=A7;B6<>B7)

Da ich die Zeilen suche, in der die eine oder die andere Bedingung gilt, verpacke ich die beiden Formeln in eine Oder() Funktion: =ODER(UND(A6=A5;B6<>B5);UND(A6=A7;B6<>B7)). Das Oder() ist dabei nicht exklusiv, es können auch beide Teile WAHR ergeben, damit die Oder() Funktion ein WAHR zurückgibt. (Für unseren Zweck ist das egal, bei drei in Spalte A gleichen/in Spalte B ungleichen Zeilen könnte das einen Unterschied machen)

Uwe

Uwe Ziegenhagen mag LaTeX und Python, auch gern in Kombination. Hat Dir dieser Beitrag geholfen und möchtest Du Dich dafür bedanken? Dann unterstütze doch vielleicht die Dingfabrik Köln e.V. mit einem kleinen Beitrag. Details zur Bezahlung findest Du unter Spenden für die Dingfabrik.

More Posts - Website

Aufgaben zum Bruchrechnen erstellen mit LaTeX und Python

Hier ein kurzes Beispiel, wie man mit Python eine TeX-Datei mit vielen Brüchen erzeugen kann. Nützlich, wenn Kinder Brüche kürzen oder erweitern sollen. In der nächsten Zeit werde ich sicher noch entsprechende Anpassungen für das Rechnen mit Brüchen hinzufügen.

EDIT: Erweitert um das Löschen der Hilfsdateien.

import os
import random
 
 
head = """
\\documentclass[14pt, twocolumn]{scrartcl}
\\usepackage[utf8]{inputenc}
\\usepackage[T1]{fontenc}
\\pagestyle{empty}
 
\\begin{document}
 
\\begin{itemize}"""
 
foot = """
\\end{itemize}
\\end{document}
"""
 
def create_bruch():
    zahlen = list(range(1,13))
    zaehler = random.choice(zahlen)
    zahlen.remove(zaehler)
    nenner = random.choice(zahlen)
    return '\\item \\( \\frac{'+ str(zaehler) + '}{' + str(nenner) + '} \\)\\vspace{1em}'
 
 
with open("Brueche.tex", "w") as document:
    document.write(head);
    for i in range(32):
        document.write(create_bruch());
    document.write(foot);
    document.close();
 
os.system("pdflatex Brueche.tex")
os.unlink("Brueche.log")
os.unlink("Brueche.aux")
os.unlink("Brueche.tex")

Brueche

Uwe

Uwe Ziegenhagen mag LaTeX und Python, auch gern in Kombination. Hat Dir dieser Beitrag geholfen und möchtest Du Dich dafür bedanken? Dann unterstütze doch vielleicht die Dingfabrik Köln e.V. mit einem kleinen Beitrag. Details zur Bezahlung findest Du unter Spenden für die Dingfabrik.

More Posts - Website