← Back to the calendar / Zurück zum Kalender

Projekttag: Fernab von X mit Python und HTML

🇬🇧 Far away from X – HTML and Python are cooler

I had a problem:

Lots of HTML files, different styles everywhere and no motivation to touch every single file manually.

So I built a small Python tool that does exactly this automatically.
And Python is supposed to help, right? Whether using VS Code or PyCharm – I like both programs.

No framework, no overkill – just a script that works and does its job.

The script:

  • reads all HTML files from an archive folder
  • creates a backup of every file before touching it
  • replaces the existing <style> block with a new one
  • if no <style> block exists, inserts one before </head>
  • has a dry-run mode – shows what would change, without changing anything
  • one exception file can be excluded (e.g. a special layout)
  • loads the new style from an external CSS file

Especially with larger archives, this saves an extreme amount of time.

A few things were important to me:

  • External CSS file: The new style lives in global-style.css – easy to update.
  • Dry-run first: See what would happen before anything is written.
  • Backup always: Every original is saved before it is touched.
  • One exception: Specific files can be skipped.

Technically, the script uses:

  • Python
  • os, re, pathlib, shutil – all from the standard library
  • No external dependencies needed
import os
import re
from pathlib import Path
from shutil import copy2

# =============================================
# Configuration – change everything here
# =============================================
ARCHIV_ORDNER = "archiv"
BACKUP_ORDNER = "archiv_backup"
STYLE_DATEI = "global-style.css"  # ← external file!

# Load new style from external file (much better!)
try:
    with open(STYLE_DATEI, encoding="utf-8") as f:
        NEW_STYLE_CONTENT = f.read().strip()
except FileNotFoundError:
    print(f"ERROR: {STYLE_DATEI} not found!")
    exit(1)


# =============================================

def fix_archive(dry_run=True):
    count = 0
    folder = Path(ARCHIV_ORDNER)

    if not folder.exists():
        print(f"Folder '{folder}' not found!")
        return

    # Create backup folder
    backup_dir = Path(BACKUP_ORDNER)
    backup_dir.mkdir(exist_ok=True)

    for filepath in folder.glob("*.html"):
        if filepath.name == "30nov1.html":  # exception
            continue

        # Create backup
        backup_path = backup_dir / filepath.name
        copy2(filepath, backup_path)
        print(f"Backup created: {backup_path}")

        with filepath.open(encoding="utf-8") as f:
            content = f.read()

        # Replace or insert style block
        if "<style>" in content:
            fixed = re.sub(
                r"<style\b[^>]*>.*?</style>",
                f"<style>\n{NEW_STYLE_CONTENT}\n</style>",
                content,
                flags=re.DOTALL | re.IGNORECASE
            )
        else:
            fixed = re.sub(
                r"(?i)</head>",
                f"<style>\n{NEW_STYLE_CONTENT}\n</style>\n</head>",
                content
            )

        if dry_run:
            print(f"[DRY RUN] Would change: {filepath}")
        else:
            with filepath.open("w", encoding="utf-8") as f:
                f.write(fixed)
            print(f"Fixed: {filepath}")
            count += 1

    print(f"\n--- DONE ---\n{count} files changed (dry_run={dry_run})")


if __name__ == "__main__":
    # First: only look, do not change anything
    fix_archive(dry_run=True)

    # When you are sure:
    # fix_archive(dry_run=False)

This makes maintaining a functional website much more relaxed, without having to fight your way through every single file.

🇩🇪 Fernab von X – HTML und Python sind cooler!

Ich hatte ein Problem:

Viele HTML-Dateien, überall unterschiedliche Styles und keine Lust, jede Datei einzeln anzufassen.

Also habe ich mir ein kleines Python-Tool gebaut, das genau das automatisch erledigt.
Und Python soll ja helfen. Egal ob mit VS Code oder PyCharm – ich mag beide Programme.

Kein Framework, kein Overkill – einfach ein Script, das funktioniert und seinen Job macht.

Das Script:

  • liest alle HTML-Dateien aus einem Archiv-Ordner
  • erstellt von jeder Datei ein Backup, bevor sie angefasst wird
  • ersetzt den vorhandenen <style>-Block durch einen neuen
  • falls kein <style>-Block vorhanden ist, wird er vor </head> eingefügt
  • hat einen Dry-Run-Modus – zeigt was sich ändern würde, ohne etwas zu ändern
  • eine Ausnahme-Datei kann übersprungen werden (z.B. ein spezielles Layout)
  • lädt den neuen Style aus einer externen CSS-Datei

Gerade bei größeren Archiven spart das extrem Zeit.

Ein paar Dinge sind mir dabei wichtig gewesen:

  • Externe CSS-Datei: Der neue Style liegt in global-style.css – einfach zu aktualisieren.
  • Dry-Run zuerst: Sehen was passieren würde, bevor etwas geschrieben wird.
  • Backup immer: Jedes Original wird gesichert, bevor es angefasst wird.
  • Eine Ausnahme: Bestimmte Dateien können übersprungen werden.

Technisch nutzt das Script:

  • Python
  • os, re, pathlib, shutil – alles aus der Standard-Bibliothek
  • Keine externen Abhängigkeiten nötig
import os
import re
from pathlib import Path
from shutil import copy2

# =============================================
# Konfiguration – alles zentral hier ändern
# =============================================
ARCHIV_ORDNER = "archiv"
BACKUP_ORDNER = "archiv_backup"
STYLE_DATEI = "global-style.css"  # ← externe Datei!

# Neuen Style aus externer Datei laden (viel besser!)
try:
    with open(STYLE_DATEI, encoding="utf-8") as f:
        NEW_STYLE_CONTENT = f.read().strip()
except FileNotFoundError:
    print(f"FEHLER: {STYLE_DATEI} nicht gefunden!")
    exit(1)


# =============================================

def fix_archive(dry_run=True):
    count = 0
    folder = Path(ARCHIV_ORDNER)

    if not folder.exists():
        print(f"Ordner '{folder}' nicht gefunden!")
        return

    # Backup-Ordner anlegen
    backup_dir = Path(BACKUP_ORDNER)
    backup_dir.mkdir(exist_ok=True)

    for filepath in folder.glob("*.html"):
        if filepath.name == "30nov1.html":  # Ausnahme
            continue

        # Backup machen
        backup_path = backup_dir / filepath.name
        copy2(filepath, backup_path)
        print(f"Backup erstellt: {backup_path}")

        with filepath.open(encoding="utf-8") as f:
            content = f.read()

        # Style-Block ersetzen oder neu einfügen
        if "<style>" in content:
            fixed = re.sub(
                r"<style\b[^>]*>.*?</style>",
                f"<style>\n{NEW_STYLE_CONTENT}\n</style>",
                content,
                flags=re.DOTALL | re.IGNORECASE
            )
        else:
            fixed = re.sub(
                r"(?i)</head>",
                f"<style>\n{NEW_STYLE_CONTENT}\n</style>\n</head>",
                content
            )

        if dry_run:
            print(f"[DRY RUN] Würde ändern: {filepath}")
        else:
            with filepath.open("w", encoding="utf-8") as f:
                f.write(fixed)
            print(f"Repariert: {filepath}")
            count += 1

    print(f"\n--- FERTIG ---\n{count} Dateien verändert (dry_run={dry_run})")


if __name__ == "__main__":
    # Erstmal nur schauen, ohne zu ändern
    fix_archive(dry_run=True)

    # Wenn du sicher bist:
    # fix_archive(dry_run=False)

So klappt es auch deutlich entspannter mit einer funktionierenden Webseite, ohne sich durch jede einzelne Datei kämpfen zu müssen.

Dieser Python-Code ist mein geistiges Eigentum. Ich stelle ihn all jenen zur Verfügung, die den HTML-Code ihrer Webseite bereinigen möchten.

🤓 Python Day – ich werde ab und zu solche kleinen Tools teilen. 🤓
Ist besser als das Chaos auf X – und angenehmer einfach drauf loszubauen.

← Vorheriger Fall / Previous case Zurück zum Archiv / Back to archive →