From 5776f2b4d7d4e699c9550aa716d7d1185c28e908 Mon Sep 17 00:00:00 2001 From: Floke Date: Sat, 10 May 2025 22:18:19 +0000 Subject: [PATCH] v1.7.3 Erweitertes Spaltenschema und Neustrukturierung MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- brancheneinstufung.py | 89 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 86 insertions(+), 3 deletions(-) diff --git a/brancheneinstufung.py b/brancheneinstufung.py index 460accf4..2bbdf9a2 100644 --- a/brancheneinstufung.py +++ b/brancheneinstufung.py @@ -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]}...'" )