Protokoll #33306

ID33306
Zeitstempel2026-04-20 23:54:06.443084
Clientroot
IP62.246.34.195
Modellclaude-sonnet-4-20250514
Statuscompleted
Tokens5,215 (Input: 2,602, Output: 2,613)
Dauer63 ms
Request-Zeit2026-04-20 23:54:06.443084
Response-Zeit2026-04-20 23:54:06.506032

Request

{
    "event": "PreToolUse",
    "tool_name": "Write",
    "tool_input": {
        "file_path": "\/var\/www\/dev.campus.systemische-tools.de\/crawler\/planung\/00-planung.md",
        "content": "# Web-Crawler für campus-am-see.de — Planung\n\n**Stand:** 2026-04-20\n**Projekt-Root:** `\/var\/www\/dev.campus.systemische-tools.de\/crawler\/`\n**Ziel-Site:** `https:\/\/campus-am-see.de\/` (inkl. eventueller Subdomains)\n**Datenbank:** neue MariaDB-DB `crawler` (mit Crawl-Historie)\n\n---\n\n## 1. Ziele & Anforderungen\n\n### 1.1 Funktionale Ziele\n- **Vollständige URL-Erfassung** der Zieldomain `campus-am-see.de` und aller erreichbaren Subdomains.\n- **Zwei Crawl-Modi:**\n  - **Fast Mode** (HTTP-basiert, curl\/httpx): maximaler Durchsatz, Link-Discovery, HTML-Parsing.\n  - **Full Mode** (Playwright \/ Headless Chromium): DOM nach JS-Ausführung, Ressourcen, JS-Fehler, Render-Metriken.\n- **Externe Links** werden vollständig mitgeloggt; jedes externe Ziel wird per HEAD\/GET auf Erreichbarkeit geprüft (Status, Final-URL, Response-Time).\n- **Erfassung aller SEO-relevanten Felder** pro URL (siehe §4).\n- **Historie:** Jeder Crawl ist ein separater Datensatz; URLs können über Crawls hinweg verglichen werden (Diff-Analysen).\n- **Trigger:** CLI-gestartet (manuell) **und** zeitgesteuert (Cron).\n\n### 1.2 Nicht-Ziele\n- Keine Einhaltung von `robots.txt` \/ `noindex` \/ Crawl-Delay-Richtlinien (eigene Site).\n- Keine Suchmaschinen-Simulation (kein Rendering-Budget, kein Link-Graph-PageRank).\n- Keine Cloud-Distribution; Ausführung lokal auf diesem Server.\n\n---\n\n## 2. Technologie-Entscheidung\n\n### 2.1 Bewertungsfaktoren und Gewichtung\n\n| Faktor | Gewicht | Begründung |\n|--------|---------|------------|\n| **Headless-Browser-Integration (Playwright\/Chromium)** | 25 % | Kernanforderung §1.1 Full Mode; ohne stabiles Binding kein Projekt. |\n| **HTTP-Durchsatz & Async-Fähigkeit** | 20 % | Fast-Mode muss tausende URLs\/min schaffen. |\n| **HTML\/DOM-Parser-Ökosystem** | 15 % | Extraktion aller SEO-Felder inkl. JSON-LD, OG, Hreflang. |\n| **Bestehende Infrastruktur \/ Team-Fit** | 15 % | Server hat Python-Pipeline (`\/var\/www\/scripts\/pipeline\/`), venv, MariaDB. |\n| **Entwicklungsgeschwindigkeit** | 10 % | Time-to-first-result. |\n| **Typsicherheit & Wartbarkeit** | 10 % | Langfristige Pflege, Schema-Änderungen. |\n| **Deployment \/ Build-Aufwand** | 5 % | Binär vs. Interpreter; Hooks zu Quality-Checks. |\n\n### 2.2 Bewertung (1 = schlecht, 10 = exzellent)\n\n| Faktor (Gewicht) | Rust | Python | PHP |\n|---|---|---|---|\n| Playwright \/ Chromium (25 %) | 4 — nur Community-Bindings (`playwright-rust`, `headless_chrome`), kein offizieller Support, Feature-Lag | **10** — offizielles Paket `playwright`, identische API wie Node\/Python-Referenz | 3 — inoffizielle Bindings (`playwright-php`), Chrome-Protokoll-Libs unvollständig |\n| HTTP-Durchsatz & Async (20 %) | **10** — tokio + reqwest, native Parallelität, kein GIL | 8 — `httpx`\/`aiohttp` asyncio, GIL für CPU-lastiges Parsen, aber Crawling ist I\/O-dominant | 5 — Guzzle async, ReactPHP, kein natives Thread-Modell |\n| HTML\/DOM-Parser-Ökosystem (15 %) | 7 — `scraper`, `select`, `html5ever` solide, aber weniger SEO-spezifisch | **10** — BeautifulSoup, lxml, Scrapy, extruct (JSON-LD\/Microdata\/RDFa) | 7 — Symfony DomCrawler, Goutte |\n| Bestehende Infrastruktur (15 %) | 3 — keine Rust-Toolchain, neuer Build-Flow | **10** — venv + Pipeline etabliert, Konstanten in `constants.py`, DB-Zugriff via `get_db_password()` | 8 — PHP ist Haupt-Stack, aber Crawler ist Standalone-Workload |\n| Entwicklungsgeschwindigkeit (10 %) | 5 — Ownership\/Lifetimes, längere Iteration | **9** — Rapid Prototyping, REPL | 8 — solide |\n| Typsicherheit\/Wartbarkeit (10 %) | **10** — compile-time Garantien | 7 — mit `mypy` + Pydantic akzeptabel | 7 — mit PHPStan akzeptabel |\n| Deployment (5 %) | 6 — Binary, aber neue Toolchain | **9** — venv vorhanden | 8 — bereits produktiv |\n\n### 2.3 Gewichtete Gesamtpunktzahl\n\n| Sprache | Rechnung | Punkte |\n|---|---|---|\n| **Python** | 10·0.25 + 8·0.20 + 10·0.15 + 10·0.15 + 9·0.10 + 7·0.10 + 9·0.05 | **9.10** |\n| Rust | 4·0.25 + 10·0.20 + 7·0.15 + 3·0.15 + 5·0.10 + 10·0.10 + 6·0.05 | 6.10 |\n| PHP | 3·0.25 + 5·0.20 + 7·0.15 + 8·0.15 + 8·0.10 + 7·0.10 + 8·0.05 | 6.10 |\n\n### 2.4 Entscheidung\n\n**Python** ist die klare Wahl. Begründung:\n1. Playwright bietet in Python First-Class-Support mit denselben Features wie das Node-Referenz-SDK — kritisch für den Full Mode.\n2. Die bestehende Pipeline, venv, Secret-Handling (`config.get_db_password()`) und Konstanten (`constants.py`) werden direkt wiederverwendet.\n3. Für reines I\/O-bound Crawling reicht asyncio; Rust’s Performance-Vorsprung amortisiert den fehlenden Playwright-Support nicht.\n4. HTML-Parsing + strukturierte Daten (`extruct`, `beautifulsoup4`, `lxml`) sind in Python am ausgereiftesten.\n\n**Wann Rust erwogen würde:** Wenn das Fast-Mode-Volumen > 100k URLs\/min werden sollte und Playwright-Anteil < 10 %. Für diese Site (Größenordnung geschätzt 100–10 000 URLs) nicht relevant.\n\n---\n\n## 3. Architektur\n\n### 3.1 Komponenten\n\n```\ncrawler\/\n├── planung\/               # Diese Dokumente\n├── src\/\n│   ├── __init__.py\n│   ├── run.py             # CLI-Entry (argparse)\n│   ├── config.py          # ENV-Loader, DB-Credentials, Defaults\n│   ├── constants.py       # Lokale Konstanten (keine Magic Numbers)\n│   ├── core\/\n│   │   ├── queue.py       # URL-Queue (DB-backed, idempotent)\n│   │   ├── dedupe.py      # URL-Normalisierung + Hashing\n│   │   ├── scheduler.py   # Orchestriert Worker, Rate-Limit\n│   │   ├── fetcher_http.py        # httpx-basiert (Fast Mode)\n│   │   ├── fetcher_playwright.py  # Chromium (Full Mode)\n│   │   ├── parser_html.py         # BeautifulSoup\/lxml → SEO-Felder\n│   │   ├── parser_structured.py   # extruct → JSON-LD, Microdata, OG\n│   │   ├── link_extractor.py      # Interne\/externe Link-Trennung\n│   │   ├── external_checker.py    # HEAD\/GET auf externe Ziele\n│   │   └── screenshot.py          # Optionaler Full-Page-Screenshot\n│   ├── db\/\n│   │   ├── connection.py\n│   │   ├── schema.sql\n│   │   ├── migrations\/\n│   │   └── repository.py  # CRUD gegen alle Tabellen\n│   └── cli\/\n│       ├── crawl.py       # `crawler crawl --mode=fast|full|hybrid`\n│       ├── report.py      # `crawler report --crawl-id=N`\n│       └── diff.py        # `crawler diff --from=N --to=M`\n├── requirements.txt\n├── setup.cfg              # mypy, flake8\n├── README.md\n└── systemd\/\n    └── crawler.service    # Optional für Cron\/Timer\n```\n\n### 3.2 Crawl-Ablauf\n\n```\n         ┌─────────────────┐\n         │  CLI \/ Cron     │\n         └────────┬────────┘\n                  ▼\n         ┌─────────────────┐\n         │  Scheduler      │──► Crawl-Run in DB anlegen\n         └────────┬────────┘\n                  ▼\n         ┌─────────────────┐\n         │  Queue (DB)     │◄────────────┐\n         └────────┬────────┘             │\n                  ▼                       │\n         ┌─────────────────┐             │\n         │  Fetcher        │             │\n         │  (HTTP|PW)      │             │\n         └────────┬────────┘             │\n                  ▼                       │\n         ┌─────────────────┐             │\n         │  Parser         │             │\n         │  (SEO-Felder)   │             │\n         └────────┬────────┘             │\n                  ▼                       │\n         ┌─────────────────┐             │\n         │  Link-Extractor │── neue URLs ┘\n         └────────┬────────┘\n                  ▼\n         ┌─────────────────┐\n         │  Repository     │──► pages, links, images, resources, errors\n         └─────────────────┘\n```\n\n### 3.3 Modi\n\n| Modus | Fetcher | Zweck |\n|-------|---------|-------|\n| `fast` | httpx (async, Pool = z. B. 20) | Reines HTML, statische Meta-Tags, Link-Discovery. ~50–200 URLs\/s. |\n| `full` | Playwright (Chromium, Pool = z. B. 4) | Gerenderter DOM, JS-Fehler, Ressourcen-Waterfall, Screenshot. ~1–5 URLs\/s. |\n| `hybrid` | fast zuerst → full für alle entdeckten URLs | Empfohlen für Voll-Audit. |\n\n### 3.4 Parallelität & Limits\n- **Interne Requests:** asyncio-Semaphore (Fast) \/ Playwright-BrowserContext-Pool (Full). Werte konfigurierbar in `constants.py`, keine Magic Numbers.\n- **Externe Link-Prüfung:** separater, gedrosselter Worker (z. B. 5 parallel, HEAD mit GET-Fallback).\n- **Retry-Logik:** exponential Backoff bei 5xx\/Timeout, max. 3 Versuche.\n\n---\n\n## 4. Erfasste SEO-Felder\n\n### 4.1 HTTP-Ebene\n- `url`, `final_url` (nach Redirects), `redirect_chain` (JSON-Array)\n- `http_status`, `http_status_history`\n- `response_time_ms`, `ttfb_ms`\n- `content_type`, `content_length`, `content_encoding`\n- `last_modified`, `etag`, `cache_control`, `server`, `x_powered_by`\n- `hsts`, `csp`, `x_frame_options`, `x_content_type_options` (Security-Header, SEO-relevant)\n\n### 4.2 HTML-Head\n- `title`, `title_length`\n- `meta_description`, `meta_description_length`\n- `meta_keywords`\n- `meta_robots` (index\/noindex, follow\/nofollow)\n- `canonical`\n- `hreflang[]` (JSON: `{lang, url}`)\n- `lang` (html[lang])\n- `charset`\n- `viewport`\n- `favicon`\n- `author`, `publisher`, `generator`\n\n### 4.3 Open Graph \/ Twitter \/ Dublin Core\n- `og_title`, `og_description`, `og_image`, `og_type`, `og_url`, `og_site_name`, `og_locale`\n- `twitter_card`, `twitter_title`, `twitter_description`, `twitter_image`, `twitter_site`, `twitter_creator`\n- `dc_*` (Dublin Core, falls vorhanden)\n\n### 4.4 Strukturierte Daten\n- JSON-LD (Array, vollständig)\n- Microdata\n- RDFa\n- Schema.org-Typen (extrahiert)\n\n### 4.5 HTML-Body\n- `h1_count`, `h1_texts[]` (alle h1, inkl. Warnung bei >1)\n- `h2_count`, `h2_texts[]`\n- `h3_count` … `h6_count` (nur Counts + erste N Texte)\n- `word_count`, `text_content` (normalisiert, optional gehasht)\n- `text_hash` (SHA-256 für Duplicate-Detection)\n- `readability_score` (Flesch-Index, optional)\n\n### 4.6 Links\nPro Link eigene Zeile in `links`:\n- `source_url_id`, `target_url`, `target_url_id` (falls intern\/bekannt)\n- `anchor_text`, `rel[]` (nofollow, sponsored, ugc, external)\n- `is_internal`, `is_external`\n- `position` (header\/nav\/main\/aside\/footer — heuristisch)\n- bei externen: `external_http_status`, `external_final_url`, `external_error`\n\n### 4.7 Bilder\nPro Bild eigene Zeile in `images`:\n- `src`, `alt`, `title`, `width`... [TRUNCATED-35a4a9d77633407b]"
    }
}

Response

{
    "tool_response": {
        "type": "create",
        "filePath": "\/var\/www\/dev.campus.systemische-tools.de\/crawler\/planung\/00-planung.md",
        "content": "# Web-Crawler für campus-am-see.de — Planung\n\n**Stand:** 2026-04-20\n**Projekt-Root:** `\/var\/www\/dev.campus.systemische-tools.de\/crawler\/`\n**Ziel-Site:** `https:\/\/campus-am-see.de\/` (inkl. eventueller Subdomains)\n**Datenbank:** neue MariaDB-DB `crawler` (mit Crawl-Historie)\n\n---\n\n## 1. Ziele & Anforderungen\n\n### 1.1 Funktionale Ziele\n- **Vollständige URL-Erfassung** der Zieldomain `campus-am-see.de` und aller erreichbaren Subdomains.\n- **Zwei Crawl-Modi:**\n  - **Fast Mode** (HTTP-basiert, curl\/httpx): maximaler Durchsatz, Link-Discovery, HTML-Parsing.\n  - **Full Mode** (Playwright \/ Headless Chromium): DOM nach JS-Ausführung, Ressourcen, JS-Fehler, Render-Metriken.\n- **Externe Links** werden vollständig mitgeloggt; jedes externe Ziel wird per HEAD\/GET auf Erreichbarkeit geprüft (Status, Final-URL, Response-Time).\n- **Erfassung aller SEO-relevanten Felder** pro URL (siehe §4).\n- **Historie:** Jeder Crawl ist ein separater Datensatz; URLs können über Crawls hinweg verglichen werden (Diff-Analysen).\n- **Trigger:** CLI-gestartet (manuell) **und** zeitgesteuert (Cron).\n\n### 1.2 Nicht-Ziele\n- Keine Einhaltung von `robots.txt` \/ `noindex` \/ Crawl-Delay-Richtlinien (eigene Site).\n- Keine Suchmaschinen-Simulation (kein Rendering-Budget, kein Link-Graph-PageRank).\n- Keine Cloud-Distribution; Ausführung lokal auf diesem Server.\n\n---\n\n## 2. Technologie-Entscheidung\n\n### 2.1 Bewertungsfaktoren und Gewichtung\n\n| Faktor | Gewicht | Begründung |\n|--------|---------|------------|\n| **Headless-Browser-Integration (Playwright\/Chromium)** | 25 % | Kernanforderung §1.1 Full Mode; ohne stabiles Binding kein Projekt. |\n| **HTTP-Durchsatz & Async-Fähigkeit** | 20 % | Fast-Mode muss tausende URLs\/min schaffen. |\n| **HTML\/DOM-Parser-Ökosystem** | 15 % | Extraktion aller SEO-Felder inkl. JSON-LD, OG, Hreflang. |\n| **Bestehende Infrastruktur \/ Team-Fit** | 15 % | Server hat Python-Pipeline (`\/var\/www\/scripts\/pipeline\/`), venv, MariaDB. |\n| **Entwicklungsgeschwindigkeit** | 10 % | Time-to-first-result. |\n| **Typsicherheit & Wartbarkeit** | 10 % | Langfristige Pflege, Schema-Änderungen. |\n| **Deployment \/ Build-Aufwand** | 5 % | Binär vs. Interpreter; Hooks zu Quality-Checks. |\n\n### 2.2 Bewertung (1 = schlecht, 10 = exzellent)\n\n| Faktor (Gewicht) | Rust | Python | PHP |\n|---|---|---|---|\n| Playwright \/ Chromium (25 %) | 4 — nur Community-Bindings (`playwright-rust`, `headless_chrome`), kein offizieller Support, Feature-Lag | **10** — offizielles Paket `playwright`, identische API wie Node\/Python-Referenz | 3 — inoffizielle Bindings (`playwright-php`), Chrome-Protokoll-Libs unvollständig |\n| HTTP-Durchsatz & Async (20 %) | **10** — tokio + reqwest, native Parallelität, kein GIL | 8 — `httpx`\/`aiohttp` asyncio, GIL für CPU-lastiges Parsen, aber Crawling ist I\/O-dominant | 5 — Guzzle async, ReactPHP, kein natives Thread-Modell |\n| HTML\/DOM-Parser-Ökosystem (15 %) | 7 — `scraper`, `select`, `html5ever` solide, aber weniger SEO-spezifisch | **10** — BeautifulSoup, lxml, Scrapy, extruct (JSON-LD\/Microdata\/RDFa) | 7 — Symfony DomCrawler, Goutte |\n| Bestehende Infrastruktur (15 %) | 3 — keine Rust-Toolchain, neuer Build-Flow | **10** — venv + Pipeline etabliert, Konstanten in `constants.py`, DB-Zugriff via `get_db_password()` | 8 — PHP ist Haupt-Stack, aber Crawler ist Standalone-Workload |\n| Entwicklungsgeschwindigkeit (10 %) | 5 — Ownership\/Lifetimes, längere Iteration | **9** — Rapid Prototyping, REPL | 8 — solide |\n| Typsicherheit\/Wartbarkeit (10 %) | **10** — compile-time Garantien | 7 — mit `mypy` + Pydantic akzeptabel | 7 — mit PHPStan akzeptabel |\n| Deployment (5 %) | 6 — Binary, aber neue Toolchain | **9** — venv vorhanden | 8 — bereits produktiv |\n\n### 2.3 Gewichtete Gesamtpunktzahl\n\n| Sprache | Rechnung | Punkte |\n|---|---|---|\n| **Python** | 10·0.25 + 8·0.20 + 10·0.15 + 10·0.15 + 9·0.10 + 7·0.10 + 9·0.05 | **9.10** |\n| Rust | 4·0.25 + 10·0.20 + 7·0.15 + 3·0.15 + 5·0.10 + 10·0.10 + 6·0.05 | 6.10 |\n| PHP | 3·0.25 + 5·0.20 + 7·0.15 + 8·0.15 + 8·0.10 + 7·0.10 + 8·0.05 | 6.10 |\n\n### 2.4 Entscheidung\n\n**Python** ist die klare Wahl. Begründung:\n1. Playwright bietet in Python First-Class-Support mit denselben Features wie das Node-Referenz-SDK — kritisch für den Full Mode.\n2. Die bestehende Pipeline, venv, Secret-Handling (`config.get_db_password()`) und Konstanten (`constants.py`) werden direkt wiederverwendet.\n3. Für reines I\/O-bound Crawling reicht asyncio; Rust’s Performance-Vorsprung amortisiert den fehlenden Playwright-Support nicht.\n4. HTML-Parsing + strukturierte Daten (`extruct`, `beautifulsoup4`, `lxml`) sind in Python am ausgereiftesten.\n\n**Wann Rust erwogen würde:** Wenn das Fast-Mode-Volumen > 100k URLs\/min werden sollte und Playwright-Anteil < 10 %. Für diese Site (Größenordnung geschätzt 100–10 000 URLs) nicht relevant.\n\n---\n\n## 3. Architektur\n\n### 3.1 Komponenten\n\n```\ncrawler\/\n├── planung\/               # Diese Dokumente\n├── src\/\n│   ├── __init__.py\n│   ├── run.py             # CLI-Entry (argparse)\n│   ├── config.py          # ENV-Loader, DB-Credentials, Defaults\n│   ├── constants.py       # Lokale Konstanten (keine Magic Numbers)\n│   ├── core\/\n│   │   ├── queue.py       # URL-Queue (DB-backed, idempotent)\n│   │   ├── dedupe.py      # URL-Normalisierung + Hashing\n│   │   ├── scheduler.py   # Orchestriert Worker, Rate-Limit\n│   │   ├── fetcher_http.py        # httpx-basiert (Fast Mode)\n│   │   ├── fetcher_playwright.py  # Chromium (Full Mode)\n│   │   ├── parser_html.py         # BeautifulSoup\/lxml → SEO-Felder\n│   │   ├── parser_structured.py   # extruct → JSON-LD, Microdata, OG\n│   │   ├── link_extractor.py      # Interne\/externe Link-Trennung\n│   │   ├── external_checker.py    # HEAD\/GET auf externe Ziele\n│   │   └── screenshot.py          # Optionaler Full-Page-Screenshot\n│   ├── db\/\n│   │   ├── connection.py\n│   │   ├── schema.sql\n│   │   ├── migrations\/\n│   │   └── repository.py  # CRUD gegen alle Tabellen\n│   └── cli\/\n│       ├── crawl.py       # `crawler crawl --mode=fast|full|hybrid`\n│       ├── report.py      # `crawler report --crawl-id=N`\n│       └── diff.py        # `crawler diff --from=N --to=M`\n├── requirements.txt\n├── setup.cfg              # mypy, flake8\n├── README.md\n└── systemd\/\n    └── crawler.service    # Optional für Cron\/Timer\n```\n\n### 3.2 Crawl-Ablauf\n\n```\n         ┌─────────────────┐\n         │  CLI \/ Cron     │\n         └────────┬────────┘\n                  ▼\n         ┌─────────────────┐\n         │  Scheduler      │──► Crawl-Run in DB anlegen\n         └────────┬────────┘\n                  ▼\n         ┌─────────────────┐\n         │  Queue (DB)     │◄────────────┐\n         └────────┬────────┘             │\n                  ▼                       │\n         ┌─────────────────┐             │\n         │  Fetcher        │             │\n         │  (HTTP|PW)      │             │\n         └────────┬────────┘             │\n                  ▼                       │\n         ┌─────────────────┐             │\n         │  Parser         │             │\n         │  (SEO-Felder)   │             │\n         └────────┬────────┘             │\n                  ▼                       │\n         ┌─────────────────┐             │\n         │  Link-Extractor │── neue URLs ┘\n         └────────┬────────┘\n                  ▼\n         ┌─────────────────┐\n         │  Repository     │──► pages, links, images, resources, errors\n         └─────────────────┘\n```\n\n### 3.3 Modi\n\n| Modus | Fetcher | Zweck |\n|-------|---------|-------|\n| `fast` | httpx (async, Pool = z. B. 20) | Reines HTML, statische Meta-Tags, Link-Discovery. ~50–200 URLs\/s. |\n| `full` | Playwright (Chromium, Pool = z. B. 4) | Gerenderter DOM, JS-Fehler, Ressourcen-Waterfall, Screenshot. ~1–5 URLs\/s. |\n| `hybrid` | fast zuerst → full für alle entdeckten URLs | Empfohlen für Voll-Audit. |\n\n### 3.4 Parallelität & Limits\n- **Interne Requests:** asyncio-Semaphore (Fast) \/ Playwright-BrowserContext-Pool (Full). Werte konfigurierbar in `constants.py`, keine Magic Numbers.\n- **Externe Link-Prüfung:** separater, gedrosselter Worker (z. B. 5 parallel, HEAD mit GET-Fallback).\n- **Retry-Logik:** exponential Backoff bei 5xx\/Timeout, max. 3 Versuche.\n\n---\n\n## 4. Erfasste SEO-Felder\n\n### 4.1 HTTP-Ebene\n- `url`, `final_url` (nach Redirects), `redirect_chain` (JSON-Array)\n- `http_status`, `http_status_history`\n- `response_time_ms`, `ttfb_ms`\n- `content_type`, `content_length`, `content_encoding`\n- `last_modified`, `etag`, `cache_control`, `server`, `x_powered_by`\n- `hsts`, `csp`, `x_frame_options`, `x_content_type_options` (Security-Header, SEO-relevant)\n\n### 4.2 HTML-Head\n- `title`, `title_length`\n- `meta_description`, `meta_description_length`\n- `meta_keywords`\n- `meta_robots` (index\/noindex, follow\/nofollow)\n- `canonical`\n- `hreflang[]` (JSON: `{lang, url}`)\n- `lang` (html[lang])\n- `charset`\n- `viewport`\n- `favicon`\n- `author`, `publisher`, `generator`\n\n### 4.3 Open Graph \/ Twitter \/ Dublin Core\n- `og_title`, `og_description`, `og_image`, `og_type`, `og_url`, `og_site_name`, `og_locale`\n- `twitter_card`, `twitter_title`, `twitter_description`, `twitter_image`, `twitter_site`, `twitter_creator`\n- `dc_*` (Dublin Core, falls vorhanden)\n\n### 4.4 Strukturierte Daten\n- JSON-LD (Array, vollständig)\n- Microdata\n- RDFa\n- Schema.org-Typen (extrahiert)\n\n### 4.5 HTML-Body\n- `h1_count`, `h1_texts[]` (alle h1, inkl. Warnung bei >1)\n- `h2_count`, `h2_texts[]`\n- `h3_count` … `h6_count` (nur Counts + erste N Texte)\n- `word_count`, `text_content` (normalisiert, optional gehasht)\n- `text_hash` (SHA-256 für Duplicate-Detection)\n- `readability_score` (Flesch-Index, optional)\n\n### 4.6 Links\nPro Link eigene Zeile in `links`:\n- `source_url_id`, `target_url`, `target_url_id` (falls intern\/bekannt)\n- `anchor_text`, `rel[]` (nofollow, sponsored, ugc, external)\n- `is_internal`, `is_external`\n- `position` (header\/nav\/main\/aside\/footer — heuristisch)\n- bei externen: `external_http_status`, `external_final_url`, `external_error`\n\n### 4.7 Bilder\nPro Bild eigene Zeile in `images`:\n- `src`, `alt`, `title`, `width`... [TRUNCATED-35a4a9d77633407b]",
        "structuredPatch": [],
        "originalFile": null,
        "userModified": false
    }
}
← Vorheriger Zur Liste Nächster →