v1.7.3 Erweitertes Spaltenschema und Neustrukturierung

Umfangreiche Überarbeitung der Spaltenstruktur im Google Sheet und im Code zur Verbesserung der thematischen Gruppierung und zur Erfassung zusätzlicher Datenpunkte.

**Wesentliche Änderungen:**
- **Neue Spalten eingeführt:**
    - "CRM Land" (F): Für das Land des Unternehmenssitzes laut CRM.
    - "Wiki Sitz Stadt" (O): Für die aus der Wikipedia-Infobox extrahierte Stadt.
    - "Wiki Sitz Land" (P): Für das aus der Wikipedia-Infobox extrahierte Land.
    - "Website Meta-Details" (AE): Für strukturierte Metadaten der Website (Title, Description, H-Tags).
    - "URL Prüfstatus" (AG): Zur Markierung von URLs, die eine erneute Prüfung/Suche benötigen.
- **Spalten neu gruppiert:**
    - Wikipedia-bezogene Timestamps (alt AN, AX, AY) wurden in den Wikipedia-Datenblock (neu V, W, X) verschoben.
    - Website Scrape Timestamp (alt AT) wurde in den Website-Datenblock (neu AF) verschoben.
    - Die Reihenfolge vieler nachfolgender Blöcke (ChatGPT-Evaluationen, LinkedIn, Konsolidierung, ML, restliche System-Timestamps) wurde angepasst, um die neue Struktur widerzuspiegeln.
    - Das Schema umfasst nun 56 Spalten (A-BD).
- **`COLUMN_MAP` aktualisiert:** Die Konstante wurde an die neue Spaltenstruktur mit 56 Einträgen angepasst.
- **`alignment_demo` überarbeitet:** Die Funktion wurde komplett aktualisiert, um alle 56 Spalten mit detaillierten Beschreibungen für Quelle, Feldkategorie, Kurzbeschreibung und Aufgabe/Funktion abzudecken.
- **`WikipediaScraper` erweitert:**
    - `keywords_map` um "sitz" erweitert.
    - `_extract_infobox_value` angepasst, um den rohen Sitz-Text zu extrahieren.
    - `extract_company_data` implementiert eine Heuristik, um aus dem rohen Sitz-Text "Wiki Sitz Stadt" und "Wiki Sitz Land" zu trennen und zurückzugeben.

**Ziel:**
- Schaffung einer logischeren und erweiterbaren Datenstruktur im Google Sheet.
- Ermöglichung der Erfassung und Analyse des Unternehmenslandes für zukünftige Auswertungen (z.B. DACH-Region).
- Konsolidierung der Dokumentation durch eine aktuelle und vollständige `alignment_demo`.

**Nächste Schritte:** Anpassung der `DataProcessor`-Methoden an die neue Spaltenstruktur.
This commit is contained in:
2025-05-10 22:18:19 +00:00
parent 57f6be7d8d
commit 5776f2b4d7

View File

@@ -107,7 +107,7 @@ PATTERNS_FILE_JSON = "technician_patterns.json" # Neu (Empfohlen)
# --- Globale Konfiguration Klasse ---
class Config:
"""Zentrale Konfigurationseinstellungen."""
VERSION = "v1.7.2"
VERSION = "v1.7.3"
LANG = "de" # Sprache fuer Wikipedia etc.
# ACHTUNG: SHEET_URL ist hier ein Platzhalter. Ersetzen Sie ihn durch Ihre tatsaechliche URL.
SHEET_URL = "https://docs.google.com/spreadsheets/d/1u_gHr9JUfmV1-iviRzbSe3575QEp7KLhK5jFV_gJcgo" # <<< ERSETZEN SIE DIES!
@@ -2950,6 +2950,7 @@ class WikipediaScraper:
'branche': ['branche', 'wirtschaftszweig', 'industry', 'taetigkeit', 'sektor', 'produkte', 'leistungen'],
'umsatz': ['umsatz', 'erloes', 'revenue', 'jahresumsatz', 'konzernumsatz', 'ergebnis'],
'mitarbeiter': ['mitarbeiter', 'mitarbeiterzahl', 'beschaeftigte', 'employees', 'number of employees', 'personal', 'belegschaft']
'sitz': ['sitz', 'hauptsitz', 'unternehmenssitz', 'firmensitz', 'headquarters', 'standort', 'sitz des unternehmens', 'anschrift', 'adresse'] # <<< NEU / ERWEITERT
}
# Konfiguriere die wikipedia-Bibliothek
@@ -3249,6 +3250,22 @@ class WikipediaScraper:
self.logger.info( # <<< GEÄNDERT
f" --> Mitarbeiter extrahiert (aus '{raw_value_text[:50]}...'): '{value_found}'"
)
elif target == 'sitz': # Wir nennen es intern 'sitz', um den ganzen String zu bekommen
# Logik zum Extrahieren des gesamten Sitz-Strings (weitgehend wie zuvor für Branche)
for sup in value_cell.find_all(['sup', 'span']):
if ( (sup.name == 'sup' and sup.has_attr('class') and 'reference' in sup['class']) or
(sup.name == 'span' and sup.get('style') and 'display:none' in sup['style']) ):
sup.decompose()
raw_sitz_text = value_cell.get_text(separator=' ', strip=True)
cleaned_sitz_text = clean_text(raw_sitz_text) # clean_text anwenden
# Manchmal gibt es mehrere Zeilen, nur die erste nehmen oder intelligent verbinden
cleaned_sitz_text = cleaned_sitz_text.split('\n')[0].strip()
value_found = cleaned_sitz_text if cleaned_sitz_text else "k.A."
self.logger.info(f" --> Roher Sitz-Text extrahiert (aus '{raw_value_text[:50]}...'): '{value_found}'")
# Die Aufteilung in Stadt und Land erfolgt in extract_company_data
break
if value_found != "k.A.":
@@ -3413,8 +3430,74 @@ class WikipediaScraper:
self.logger.debug(" -> Extrahiere Mitarbeiter aus Infobox...") # <<< GEÄNDERT
mitarbeiter_val = self._extract_infobox_value(soup, 'mitarbeiter')
self.logger.debug(" -> Extrahiere Sitz aus Infobox...")
raw_sitz_string = self._extract_infobox_value(soup, 'sitz') # Holt den gesamten Sitz-String
sitz_stadt_val = "k.A."
sitz_land_val = "k.A."
if raw_sitz_string and raw_sitz_string.lower() != "k.a.":
# Versuche Stadt und Land zu trennen (heuristisch)
# Annahme 1: "Stadt (Land)" oder "Stadt, Land"
# Annahme 2: Bekannte Länder am Ende
# Dies ist eine einfache Heuristik und kann verfeinert werden.
temp_sitz = raw_sitz_string
# Länder, nach denen wir suchen könnten (erweiterbar)
known_countries = {
"deutschland": "Deutschland", "germany": "Deutschland", "de": "Deutschland",
"österreich": "Österreich", "austria": "Österreich", "at": "Österreich",
"schweiz": "Schweiz", "switzerland": "Schweiz", "ch": "Schweiz",
"usa": "USA", "vereinigte staaten": "USA",
"frankreich": "Frankreich", "france": "Frankreich", "fr": "Frankreich",
"niederlande": "Niederlande", "netherlands": "Niederlande", "nl": "Niederlande",
"belgien": "Belgien", "belgium": "Belgien", "be": "Belgien",
"luxemburg": "Luxemburg", "luxembourg": "Luxemburg", "lu": "Luxemburg",
"italien": "Italien", "italy": "Italien", "it": "Italien",
"spanien": "Spanien", "spain": "Spanien", "es": "Spanien",
"polen": "Polen", "poland": "Polen", "pl": "Polen",
"vereinigtes königreich": "Vereinigtes Königreich", "united kingdom": "Vereinigtes Königreich", "uk": "Vereinigtes Königreich", "gb": "Vereinigtes Königreich"
}
found_country_in_string = ""
# Suche nach Land in Klammern am Ende: Stadt (Land)
klammer_match = re.search(r'\(([^)]+)\)$', temp_sitz)
if klammer_match:
potential_land_in_klammer = klammer_match.group(1).strip().lower()
if potential_land_in_klammer in known_countries:
found_country_in_string = known_countries[potential_land_in_klammer]
temp_sitz = temp_sitz[:klammer_match.start()].strip() # Rest ist Stadt
# Wenn kein Land in Klammern, suche nach Komma und bekanntem Land am Ende
if not found_country_in_string and ',' in temp_sitz:
parts = [p.strip() for p in temp_sitz.split(',')]
if len(parts) > 1:
potential_land_after_comma = parts[-1].lower()
if potential_land_after_comma in known_countries:
found_country_in_string = known_countries[potential_land_after_comma]
temp_sitz = ", ".join(parts[:-1]).strip() # Rest ist Stadt
# Wenn immer noch kein Land, aber der verbleibende String einem Land entspricht
if not found_country_in_string and temp_sitz.lower() in known_countries:
found_country_in_string = known_countries[temp_sitz.lower()]
temp_sitz = "" # Ganzer String war das Land
sitz_land_val = found_country_in_string if found_country_in_string else "k.A."
# Was übrig bleibt (oder der Originalstring, falls kein Land getrennt werden konnte), ist die Stadt
# Entferne Postleitzahlen und führende/trailing Whitespace
sitz_stadt_val = re.sub(r'^\d{4,8}\s*', '', temp_sitz).strip()
if not sitz_stadt_val and raw_sitz_string.lower() != "k.a." and sitz_land_val == "k.A.": # Wenn Stadt leer, aber Original hatte was und kein Land gefunden
sitz_stadt_val = raw_sitz_string # Nimm Original als Stadt
elif not sitz_stadt_val:
sitz_stadt_val = "k.A."
result = {
'url': page_url,
'sitz_stadt': sitz_stadt_val,
'sitz_land': sitz_land_val,
'first_paragraph': first_paragraph,
'branche': branche_val,
'umsatz': umsatz_val,
@@ -3422,8 +3505,8 @@ class WikipediaScraper:
'categories': categories_val
}
self.logger.info( # <<< GEÄNDERT
f" -> Extrahierte Daten: P='{first_paragraph[:50]}...', "
self.logger.info(
f" -> Extrahierte Daten: Sitz Stadt='{sitz_stadt_val}', Sitz Land='{sitz_land_val}', P='{first_paragraph[:30]}...', "
f"B='{branche_val}', U='{umsatz_val}', M='{mitarbeiter_val}', "
f"C='{categories_val[:50]}...'"
)