Appearance
Kapitel 17: Fortgeschrittene Praxis
🎯 Lernziele
In diesem Kapitel wirst du:
- Einen einfachen Web-Crawler programmieren
- Eine GUI-Anwendung mit Tkinter erstellen
- Datenbankoperationen mit SQLite durchführen
- Dateien mit
osundshutilverwalten
🌐 Praxis 1: Einfacher Web-Crawler
📋 Anforderungsanalyse
Funktionalitäten:
- ✅ Webseite herunterladen
- ✅ HTML parsen
- ✅ Links extrahieren
- ✅ Bilder herunterladen
💻 Vollständiger Code
python
import requests
from bs4 import BeautifulSoup
import os
def web_crawler(url, ziel_ordner="crawler_output"):
"""Einfacher Web-Crawler"""
try:
# Erstelle Zielordner
os.makedirs(ziel_ordner, exist_ok=True)
# Webseite herunterladen
print(f"Lade {url}...")
response = requests.get(url, timeout=10)
response.raise_for_status() # Fehler überprüfen
# HTML parsen
soup = BeautifulSoup(response.text, "html.parser")
# Titel extrahieren
titel = soup.title.string if soup.title else "Kein Titel"
print(f"Seitentitel: {titel}")
# Links extrahieren
links = []
for link in soup.find_all("a", href=True):
links.append(link["href"])
print(f"Gefundene Links: {len(links)}")
# Links in Datei speichern
with open(f"{ziel_ordner}/links.txt", "w", encoding="utf-8") as f:
for link in links:
f.write(link + "\n")
# Bilder herunterladen
bilder = soup.find_all("img", src=True)
print(f"Gefundene Bilder: {len(bilder)}")
for i, bild in enumerate(bilder[:5]): # Nur die ersten 5 Bilder
try:
bild_url = bild["src"]
if not bild_url.startswith("http"):
continue
bild_response = requests.get(bild_url, timeout=5)
bild_pfad = f"{ziel_ordner}/bild_{i}.jpg"
with open(bild_pfad, "wb") as f:
f.write(bild_response.content)
print(f"Bild {i+1} heruntergeladen: {bild_pfad}")
except Exception as e:
print(f"Fehler beim Herunterladen von Bild {i+1}: {e}")
print(f"\nCrawling abgeschlossen! Ergebnisse in '{ziel_ordner}'")
except requests.exceptions.RequestException as e:
print(f"Fehler beim Zugriff auf {url}: {e}")
except Exception as e:
print(f"Ein Fehler ist aufgetreten: {e}")
# Hauptprogramm
if __name__ == "__main__":
url = input("Gib die URL der Webseite ein: ")
web_crawler(url)🧪 Testlauf
Gib die URL der Webseite ein: https://example.com
Lade https://example.com...
Seitentitel: Example Domain
Gefundene Links: 1
Gefundene Bilder: 1
Bild 1 heruntergeladen: crawler_output/bild_0.jpg
Crawling abgeschlossen! Ergebnisse in 'crawler_output'🖥️ Praxis 2: GUI-Entwicklung mit Tkinter
📋 Anforderungsanalyse
Funktionalitäten:
- ✅ Einfaches Fenster erstellen
- ✅ Eingabefelder und Buttons hinzufügen
- ✅ Ereignisse (Events) behandeln
- ✅ Einfachen Taschenrechner erstellen
💻 Vollständiger Code
python
import tkinter as tk
from tkinter import messagebox
class Taschenrechner:
def __init__(self, master):
self.master = master
master.title("Einfacher Taschenrechner")
master.geometry("300x200")
# Eingabefelder
self.label1 = tk.Label(master, text="Zahl 1:")
self.label1.pack()
self.entry1 = tk.Entry(master)
self.entry1.pack()
self.label2 = tk.Label(master, text="Zahl 2:")
self.label2.pack()
self.entry2 = tk.Entry(master)
self.entry2.pack()
# Buttons
self.button_frame = tk.Frame(master)
self.button_frame.pack(pady=10)
self.add_button = tk.Button(self.button_frame, text="+", command=self.addieren)
self.add_button.pack(side=tk.LEFT, padx=5)
self.sub_button = tk.Button(self.button_frame, text="-", command=self.subtrahieren)
self.sub_button.pack(side=tk.LEFT, padx=5)
self.mul_button = tk.Button(self.button_frame, text="*", command=self.multiplizieren)
self.mul_button.pack(side=tk.LEFT, padx=5)
self.div_button = tk.Button(self.button_frame, text="/", command=self.dividieren)
self.div_button.pack(side=tk.LEFT, padx=5)
# Ergebnis
self.ergebnis_label = tk.Label(master, text="Ergebnis:")
self.ergebnis_label.pack(pady=10)
def addieren(self):
try:
zahl1 = float(self.entry1.get())
zahl2 = float(self.entry2.get())
ergebnis = zahl1 + zahl2
self.ergebnis_label.config(text=f"Ergebnis: {ergebnis}")
except ValueError:
messagebox.showerror("Fehler", "Bitte gib gültige Zahlen ein!")
def subtrahieren(self):
try:
zahl1 = float(self.entry1.get())
zahl2 = float(self.entry2.get())
ergebnis = zahl1 - zahl2
self.ergebnis_label.config(text=f"Ergebnis: {ergebnis}")
except ValueError:
messagebox.showerror("Fehler", "Bitte gib gültige Zahlen ein!")
def multiplizieren(self):
try:
zahl1 = float(self.entry1.get())
zahl2 = float(self.entry2.get())
ergebnis = zahl1 * zahl2
self.ergebnis_label.config(text=f"Ergebnis: {ergebnis}")
except ValueError:
messagebox.showerror("Fehler", "Bitte gib gültige Zahlen ein!")
def dividieren(self):
try:
zahl1 = float(self.entry1.get())
zahl2 = float(self.entry2.get())
if zahl2 == 0:
messagebox.showerror("Fehler", "Division durch Null ist nicht erlaubt!")
return
ergebnis = zahl1 / zahl2
self.ergebnis_label.config(text=f"Ergebnis: {ergebnis}")
except ValueError:
messagebox.showerror("Fehler", "Bitte gib gültige Zahlen ein!")
# Hauptprogramm
if __name__ == "__main__":
root = tk.Tk()
app = Taschenrechner(root)
root.mainloop()🧪 Testlauf
[GUI-Fenster wird angezeigt]
Zahl 1: 10
Zahl 2: 5
[+] Button klicken → Ergebnis: 15.0
[-] Button klicken → Ergebnis: 5.0
[*] Button klicken → Ergebnis: 50.0
[/] Button klicken → Ergebnis: 2.0🗄️ Praxis 3: Datenbankoperationen mit SQLite
📋 Anforderungsanalyse
Funktionalitäten:
- ✅ Datenbank erstellen
- ✅ Tabellen erstellen
- ✅ Daten einfügen
- ✅ Daten abfragen
- ✅ Daten aktualisieren und löschen
💻 Vollständiger Code
python
import sqlite3
from datetime import datetime
class Datenbank:
def __init__(self, db_name="beispiel.db"):
self.db_name = db_name
self.verbindung = None
self.cursor = None
def verbinden(self):
"""Stellt eine Verbindung zur Datenbank her"""
try:
self.verbindung = sqlite3.connect(self.db_name)
self.cursor = self.verbindung.cursor()
print(f"Mit Datenbank '{self.db_name}' verbunden.")
except sqlite3.Error as e:
print(f"Fehler beim Verbinden mit der Datenbank: {e}")
def trennen(self):
"""Trennt die Verbindung zur Datenbank"""
if self.verbindung:
self.verbindung.close()
print(f"Verbindung zur Datenbank '{self.db_name}' getrennt.")
def tabelle_erstellen(self):
"""Erstellt die Tabelle 'studenten'"""
try:
self.cursor.execute("""
CREATE TABLE IF NOT EXISTS studenten (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
alter INTEGER,
fach TEXT,
erstellt_am TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
""")
self.verbindung.commit()
print("Tabelle 'studenten' erstellt (oder bereits vorhanden).")
except sqlite3.Error as e:
print(f"Fehler beim Erstellen der Tabelle: {e}")
def student_einfügen(self, name, alter, fach):
"""Fügt einen neuen Studenten hinzu"""
try:
self.cursor.execute("""
INSERT INTO studenten (name, alter, fach)
VALUES (?, ?, ?)
""", (name, alter, fach))
self.verbindung.commit()
print(f"Student '{name}' erfolgreich hinzugefügt.")
return self.cursor.lastrowid
except sqlite3.Error as e:
print(f"Fehler beim Einfügen des Studenten: {e}")
return None
def student_abfragen(self, student_id=None):
"""Fragt Studenten ab (alle oder nach ID)"""
try:
if student_id:
self.cursor.execute("SELECT * FROM studenten WHERE id = ?", (student_id,))
student = self.cursor.fetchone()
if student:
print(f"Student gefunden: ID={student[0]}, Name={student[1]}, Alter={student[2]}, Fach={student[3]}, Erstellt am={student[4]}")
else:
print(f"Kein Student mit ID {student_id} gefunden.")
else:
self.cursor.execute("SELECT * FROM studenten")
studenten = self.cursor.fetchall()
if studenten:
print(f"\n=== Alle Studenten ({len(studenten)}) ===")
for student in studenten:
print(f" ID={student[0]}, Name={student[1]}, Alter={student[2]}, Fach={student[3]}")
else:
print("Keine Studenten in der Datenbank.")
except sqlite3.Error as e:
print(f"Fehler beim Abfragen der Studenten: {e}")
def student_aktualisieren(self, student_id, name=None, alter=None, fach=None):
"""Aktualisiert einen Studenten"""
try:
# Überprüfen, ob der Student existiert
self.cursor.execute("SELECT * FROM studenten WHERE id = ?", (student_id,))
if not self.cursor.fetchone():
print(f"Fehler: Kein Student mit ID {student_id} gefunden.")
return False
# Aktualisierung durchführen
if name:
self.cursor.execute("UPDATE studenten SET name = ? WHERE id = ?", (name, student_id))
if alter:
self.cursor.execute("UPDATE studenten SET alter = ? WHERE id = ?", (alter, student_id))
if fach:
self.cursor.execute("UPDATE studenten SET fach = ? WHERE id = ?", (fach, student_id))
self.verbindung.commit()
print(f"Student mit ID {student_id} erfolgreich aktualisiert.")
return True
except sqlite3.Error as e:
print(f"Fehler beim Aktualisieren des Studenten: {e}")
return False
def student_löschen(self, student_id):
"""Löscht einen Studenten"""
try:
# Überprüfen, ob der Student existiert
self.cursor.execute("SELECT * FROM studenten WHERE id = ?", (student_id,))
if not self.cursor.fetchone():
print(f"Fehler: Kein Student mit ID {student_id} gefunden.")
return False
# Löschen durchführen
self.cursor.execute("DELETE FROM studenten WHERE id = ?", (student_id,))
self.verbindung.commit()
print(f"Student mit ID {student_id} erfolgreich gelöscht.")
return True
except sqlite3.Error as e:
print(f"Fehler beim Löschen des Studenten: {e}")
return False
# Hauptprogramm
if __name__ == "__main__":
db = Datenbank()
db.verbinden()
db.tabelle_erstellen()
# Studenten hinzufügen
id1 = db.student_einfügen("Max Mustermann", 20, "Informatik")
id2 = db.student_einfügen("Anna Beispiel", 22, "Mathematik")
# Studenten abfragen
db.student_abfragen()
# Student aktualisieren
if id1:
db.student_aktualisieren(id1, alter=21)
# Student löschen
if id2:
db.student_löschen(id2)
# Erneut abfragen
db.student_abfragen()
db.trennen()🧪 Testlauf
Mit Datenbank 'beispiel.db' verbunden.
Tabelle 'studenten' erstellt (oder bereits vorhanden).
Student 'Max Mustermann' erfolgreich hinzugefügt.
Student 'Anna Beispiel' erfolgreich hinzugefügt.
=== Alle Studenten (2) ===
ID=1, Name=Max Mustermann, Alter=20, Fach=Informatik
ID=2, Name=Anna Beispiel, Alter=22, Fach=Mathematik
Student mit ID 1 erfolgreich aktualisiert.
Student mit ID 2 erfolgreich gelöscht.
=== Alle Studenten (1) ===
ID=1, Name=Max Mustermann, Alter=21, Fach=Informatik
Verbindung zur Datenbank 'beispiel.db' getrennt.📂 Praxis 4: Dateiverwaltung mit os und shutil
📋 Anforderungsanalyse
Funktionalitäten:
- ✅ Dateien und Ordner erstellen
- ✅ Dateien kopieren und verschieben
- ✅ Dateien umbenennen und löschen
- ✅ Dateiinformationen abfragen
💻 Vollständiger Code
python
import os
import shutil
from datetime import datetime
class Dateiverwaltung:
def __init__(self, basis_pfad="."):
self.basis_pfad = basis_pfad
def ordner_erstellen(self, ordner_name):
"""Erstellt einen Ordner"""
try:
ordner_pfad = os.path.join(self.basis_pfad, ordner_name)
os.makedirs(ordner_pfad, exist_ok=True)
print(f"Ordner '{ordner_name}' erstellt.")
return ordner_pfad
except OSError as e:
print(f"Fehler beim Erstellen des Ordners: {e}")
return None
def datei_erstellen(self, datei_name, inhalt=""):
"""Erstellt eine Datei mit Inhalt"""
try:
datei_pfad = os.path.join(self.basis_pfad, datei_name)
with open(datei_pfad, "w", encoding="utf-8") as f:
f.write(inhalt)
print(f"Datei '{datei_name}' erstellt.")
return datei_pfad
except IOError as e:
print(f"Fehler beim Erstellen der Datei: {e}")
return None
def datei_kopieren(self, quelle, ziel):
"""Kopiert eine Datei"""
try:
quell_pfad = os.path.join(self.basis_pfad, quelle)
ziel_pfad = os.path.join(self.basis_pfad, ziel)
shutil.copy2(quell_pfad, ziel_pfad)
print(f"Datei '{quelle}' nach '{ziel}' kopiert.")
return True
except IOError as e:
print(f"Fehler beim Kopieren der Datei: {e}")
return False
def datei_verschieben(self, quelle, ziel):
"""Verschiebt eine Datei"""
try:
quell_pfad = os.path.join(self.basis_pfad, quelle)
ziel_pfad = os.path.join(self.basis_pfad, ziel)
shutil.move(quell_pfad, ziel_pfad)
print(f"Datei '{quelle}' nach '{ziel}' verschoben.")
return True
except IOError as e:
print(f"Fehler beim Verschieben der Datei: {e}")
return False
def datei_umbenennen(self, alte_name, neue_name):
"""Benennt eine Datei um"""
try:
alte_pfad = os.path.join(self.basis_pfad, alte_name)
neue_pfad = os.path.join(self.basis_pfad, neue_name)
os.rename(alte_pfad, neue_pfad)
print(f"Datei '{alte_name}' in '{neue_name}' umbenannt.")
return True
except OSError as e:
print(f"Fehler beim Umbenennen der Datei: {e}")
return False
def datei_löschen(self, datei_name):
"""Löscht eine Datei"""
try:
datei_pfad = os.path.join(self.basis_pfad, datei_name)
os.remove(datei_pfad)
print(f"Datei '{datei_name}' gelöscht.")
return True
except OSError as e:
print(f"Fehler beim Löschen der Datei: {e}")
return False
def ordner_löschen(self, ordner_name, rekursiv=False):
"""Löscht einen Ordner"""
try:
ordner_pfad = os.path.join(self.basis_pfad, ordner_name)
if rekursiv:
shutil.rmtree(ordner_pfad)
else:
os.rmdir(ordner_pfad)
print(f"Ordner '{ordner_name}' gelöscht.")
return True
except OSError as e:
print(f"Fehler beim Löschen des Ordners: {e}")
return False
def datei_info(self, datei_name):
"""Zeigt Dateiinformationen an"""
try:
datei_pfad = os.path.join(self.basis_pfad, datei_name)
info = os.stat(datei_pfad)
print(f"\n=== Dateiinformationen für '{datei_name}' ===")
print(f"Größe: {info.st_size} Bytes")
print(f"Erstellt am: {datetime.fromtimestamp(info.st_ctime)}")
print(f"Zuletzt geändert am: {datetime.fromtimestamp(info.st_mtime)}")
return info
except OSError as e:
print(f"Fehler beim Abrufen der Dateiinformationen: {e}")
return None
def dateien_auflisten(self, ordner_name=None):
"""Listet alle Dateien in einem Ordner auf"""
try:
if ordner_name:
ordner_pfad = os.path.join(self.basis_pfad, ordner_name)
else:
ordner_pfad = self.basis_pfad
dateien = os.listdir(ordner_pfad)
print(f"\n=== Dateien in '{ordner_pfad}' ===")
for datei in dateien:
datei_pfad = os.path.join(ordner_pfad, datei)
if os.path.isfile(datei_pfad):
print(f" [Datei] {datei}")
elif os.path.isdir(datei_pfad):
print(f" [Ordner] {datei}")
return dateien
except OSError as e:
print(f"Fehler beim Auflisten der Dateien: {e}")
return None
# Hauptprogramm
if __name__ == "__main__":
dv = Dateiverwaltung()
# Ordner erstellen
dv.ordner_erstellen("test_ordner")
# Dateien erstellen
dv.datei_erstellen("test1.txt", "Das ist die erste Testdatei.")
dv.datei_erstellen("test2.txt", "Das ist die zweite Testdatei.")
dv.datei_erstellen(os.path.join("test_ordner", "test3.txt"), "Das ist die dritte Testdatei im Ordner.")
# Dateien auflisten
dv.dateien_auflisten()
dv.dateien_auflisten("test_ordner")
# Datei kopieren
dv.datei_kopieren("test1.txt", "test1_kopie.txt")
# Datei verschieben
dv.datei_verschieben("test2.txt", os.path.join("test_ordner", "test2_verschoben.txt"))
# Datei umbenennen
dv.datei_umbenennen("test1_kopie.txt", "test1_neu.txt")
# Dateiinformationen anzeigen
dv.datei_info("test1_neu.txt")
# Datei löschen
dv.datei_löschen("test1_neu.txt")
# Ordner löschen (rekursiv)
dv.ordner_löschen("test_ordner", rekursiv=True)🧪 Testlauf
Ordner 'test_ordner' erstellt.
Datei 'test1.txt' erstellt.
Datei 'test2.txt' erstellt.
Datei 'test_ordner/test3.txt' erstellt.
=== Dateien in '.' ===
[Datei] test1.txt
[Datei] test2.txt
[Ordner] test_ordner
=== Dateien in 'test_ordner' ===
[Datei] test3.txt
Datei 'test1.txt' nach 'test1_kopie.txt' kopiert.
Datei 'test2.txt' nach 'test_ordner/test2_verschoben.txt' verschoben.
Datei 'test1_kopie.txt' in 'test1_neu.txt' umbenannt.
=== Dateiinformationen für 'test1_neu.txt' ===
Größe: 32 Bytes
Erstellt am: 2024-01-15 10:30:00
Zuletzt geändert am: 2024-01-15 10:30:00
Datei 'test1_neu.txt' gelöscht.
Ordner 'test_ordner' gelöscht.📝 Zusammenfassung
In diesem Kapitel hast du gelernt:
- ✅ Einen einfachen Web-Crawler zu programmieren
- ✅ Eine GUI-Anwendung mit Tkinter zu erstellen
- ✅ Datenbankoperationen mit SQLite durchzuführen
- ✅ Dateien mit
osundshutilzu verwalten
🎯 Übung
- Erweitere den Web-Crawler: Füge eine Funktion hinzu, die den Text einer Webseite extrahiert und in einer Datei speichert.
- Erweitere die GUI-Anwendung: Füge weitere Funktionen hinzu (z.B. Löschen, zurücksetzen).
- Erweitere die Datenbankoperationen: Füge eine Suchfunktion hinzu.
- Erweitere die Dateiverwaltung: Füge eine Funktion hinzu, die Dateien nach Endung filtert.
⏭️ Nächstes Kapitel
In Kapitel 18 werden wir Fehlerbehebung und Debugging lernen - wie man Fehler findet und behebt!
