Files
Amateurfunk-Anki/CLAUDE.md
T
2026-05-20 13:21:09 +02:00

3.6 KiB

Amateurfunk — BNetzA Question Catalog Downloader

A small Python tool that downloads the latest German amateur-radio exam question catalog ("Fragenkatalog") published by the Bundesnetzagentur (BNetzA) and extracts the structured JSON + SVG image assets for further use (study apps, flashcards, training tools, etc.).

The full source-discovery notes, JSON schema, and design decisions live in DESIGN.md. This file is a short orientation for anyone (human or agent) opening the project.

What the catalog is

  • Official German amateur-radio exam questions for classes N, E, A (German license tiers).
  • Published by the Bundesnetzagentur under the DL-DE→BY-2.0 open data license (free reuse, attribution required).
  • Distributed as a single ZIP containing one JSON file with the full question tree, plus a svgs/ folder with figures referenced by individual questions.
  • Current edition at time of writing: 3. Auflage, März 2024 (issued 2024-03-20, valid from 2024-06-24, ~1750 questions).

Canonical source

  • ZIP (machine-readable): https://www.bundesnetzagentur.de/SharedDocs/Downloads/DE/Sachgebiete/Telekommunikation/Unternehmen_Institutionen/Frequenzen/Amateurfunk/Fragenkatalog/PruefungsfragenZIP.zip?__blob=publicationFile
  • Landing page (short link): https://www.bnetza.de/amateurfunk-fragenkatalog
  • PDF (human-readable, not used by this tool): same path with Pruefungsfragen.pdf instead of PruefungsfragenZIP.zip.

The ZIP URL is stable across editions — BNetzA replaces the file in-place. The Last-Modified HTTP header is reliable for change detection. The filename inside the ZIP (fragenkatalog3b.json) encodes the edition (3b = 3rd edition, revision b) and will change on new editions, so we discover it from the archive rather than hard-coding.

Scope of the tool (initial)

  1. Download the ZIP from the canonical URL.
  2. Verify it is a valid ZIP and contains the expected JSON + SVG files.
  3. Extract to a target directory (default: ./data/<edition>/).
  4. Emit a small manifest.json next to the data: source URL, fetched-at timestamp, Last-Modified from the server, JSON edition metadata, sha256 of the ZIP.
  5. Be idempotent — re-running without an upstream change is a no-op. The skip key is the HTTP Last-Modified header recorded on the previous manifest; the ZIP is deleted by default after extraction, so the recorded sha256 is provenance, not a re-verification target. See DESIGN.md for the full idempotency contract.

Out of scope for v1 (kept for later): rendering LaTeX/SVG, building a study app, multi-edition diffing, mirroring the PDF.

Repo conventions

  • Python 3.11+, standard library only where reasonable (urllib, zipfile, hashlib, json, pathlib). Add deps only if they pay for themselves — none expected for v1.
  • Single-purpose script: amateurfunk_fetch.py (or a tiny package if it grows). No framework, no CLI library beyond argparse.
  • Downloaded data is treated as a build artifact: kept under data/ and gitignored.
  • License attribution string (required by DL-DE→BY-2.0) is preserved verbatim from the upstream README.txt whenever we redistribute the data.

Working on this repo

  • Start from DESIGN.md — it has the JSON schema, the question/answer conventions (answer A is always correct, B/C/D are distractors), the LaTeX-in-questions caveat, and the SVG naming convention.
  • Do not invent new download URLs; the ones in DESIGN.md were verified against the live BNetzA site.
  • When BNetzA publishes a new edition, expect a new fragenkatalog<N><rev>.json filename inside the ZIP. The downloader must not hard-code the current name.