v1.2.0: Added Alignment-Demo mode (Option 3) for new column header mapping
Zusammenfassung der Änderungen (v1.1.16 → v1.2.0) Neue Alignment-Demo (Modus 3): Ein neuer Modus „3“ wurde hinzugefügt, der ausschließlich eine Demo-Zeile (Zeile 11200) mit den neuen Spaltenüberschriften in das Google Sheet schreibt. Dies ermöglicht die Validierung der neuen Spaltenanordnung anhand einer Übersetzungstabelle. Spaltenzuordnung: Die Code-Logik für das Update der Zellen wurde so angepasst, dass bei normalen bzw. Re‑Evaluierungsmodi die korrekten Spaltenadressen genutzt werden. Sonstiges: Unicode-Normalisierung und bestehende Umsatz- sowie Mitarbeiterextraktion (v1.1.16) bleiben erhalten.
This commit is contained in:
@@ -13,7 +13,7 @@ import csv
|
|||||||
|
|
||||||
# ==================== KONFIGURATION ====================
|
# ==================== KONFIGURATION ====================
|
||||||
class Config:
|
class Config:
|
||||||
VERSION = "v1.1.16" # v1.1.16: Umsatz in Mio € & Mitarbeiterzahl extrahiert; Fallback-Debug bei fehlender Umwandlung
|
VERSION = "v1.2.0" # v1.2.0: Neue Spaltenanordnung, Alignment-Demo-Modus (Option 3)
|
||||||
LANG = "de"
|
LANG = "de"
|
||||||
CREDENTIALS_FILE = "service_account.json"
|
CREDENTIALS_FILE = "service_account.json"
|
||||||
SHEET_URL = "https://docs.google.com/spreadsheets/d/1u_gHr9JUfmV1-iviRzbSe3575QEp7KLhK5jFV_gJcgo"
|
SHEET_URL = "https://docs.google.com/spreadsheets/d/1u_gHr9JUfmV1-iviRzbSe3575QEp7KLhK5jFV_gJcgo"
|
||||||
@@ -45,7 +45,6 @@ def clean_text(text):
|
|||||||
"""Normalisiert Unicode, entfernt Referenzen und extra Whitespace."""
|
"""Normalisiert Unicode, entfernt Referenzen und extra Whitespace."""
|
||||||
if not text:
|
if not text:
|
||||||
return "k.A."
|
return "k.A."
|
||||||
# Unicode-Normalisierung (NFKC vereinheitlicht ambigue Zeichen)
|
|
||||||
text = unicodedata.normalize("NFKC", str(text))
|
text = unicodedata.normalize("NFKC", str(text))
|
||||||
text = re.sub(r'\[\d+\]', '', text)
|
text = re.sub(r'\[\d+\]', '', text)
|
||||||
text = re.sub(r'\s+', ' ', text).strip()
|
text = re.sub(r'\s+', ' ', text).strip()
|
||||||
@@ -76,14 +75,13 @@ def extract_numeric_value(raw_value, is_umsatz=False):
|
|||||||
"""
|
"""
|
||||||
Extrahiert den numerischen Wert aus raw_value.
|
Extrahiert den numerischen Wert aus raw_value.
|
||||||
- Nutzt Komma als Dezimaltrenner und entfernt Punkte als Tausendertrennzeichen.
|
- Nutzt Komma als Dezimaltrenner und entfernt Punkte als Tausendertrennzeichen.
|
||||||
- Für Umsatz: Falls "mrd" vorkommt, wird mit 1000 multipliziert; enthält der Text keine Einheit, so wird durch 1e6 geteilt.
|
- Für Umsatz: Falls "mrd" vorkommt, wird der Wert mit 1000 multipliziert; enthält der Text keine Einheit, so wird durch 1e6 geteilt.
|
||||||
- Für Mitarbeiter: Gibt den ganzzahligen Wert zurück.
|
- Für Mitarbeiter: Gibt den ganzzahligen Wert zurück.
|
||||||
- Falls die Umwandlung fehlschlägt, wird der Original-Rohtext im Debug-Log ausgegeben.
|
- Bei Fehlern wird der Original-Rohtext im Debug-Log ausgegeben.
|
||||||
"""
|
"""
|
||||||
raw_value = raw_value.strip()
|
raw_value = raw_value.strip()
|
||||||
if not raw_value:
|
if not raw_value:
|
||||||
return "k.A."
|
return "k.A."
|
||||||
# Ersetze nichtbrechende Leerzeichen durch normale Leerzeichen
|
|
||||||
raw = raw_value.lower().replace("\xa0", " ")
|
raw = raw_value.lower().replace("\xa0", " ")
|
||||||
match = re.search(r'([\d.,]+)', raw, flags=re.UNICODE)
|
match = re.search(r'([\d.,]+)', raw, flags=re.UNICODE)
|
||||||
if not match or not match.group(1).strip():
|
if not match or not match.group(1).strip():
|
||||||
@@ -96,14 +94,14 @@ def extract_numeric_value(raw_value, is_umsatz=False):
|
|||||||
num = float(num_str)
|
num = float(num_str)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
debug_print(f"Fehler bei der Umwandlung von '{num_str}' (Rohtext: '{raw_value}'): {e}")
|
debug_print(f"Fehler bei der Umwandlung von '{num_str}' (Rohtext: '{raw_value}'): {e}")
|
||||||
return raw_value # Rückgabe des Rohtexts als Fallback
|
return raw_value # Fallback: Originaltext
|
||||||
else:
|
else:
|
||||||
num_str = num_str.replace(' ', '').replace('.', '')
|
num_str = num_str.replace(' ', '').replace('.', '')
|
||||||
try:
|
try:
|
||||||
num = float(num_str)
|
num = float(num_str)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
debug_print(f"Fehler bei der Umwandlung von '{num_str}' (Rohtext: '{raw_value}'): {e}")
|
debug_print(f"Fehler bei der Umwandlung von '{num_str}' (Rohtext: '{raw_value}'): {e}")
|
||||||
return raw_value # Rückgabe des Rohtexts als Fallback
|
return raw_value # Fallback: Originaltext
|
||||||
if is_umsatz:
|
if is_umsatz:
|
||||||
if "mrd" in raw or "milliarden" in raw:
|
if "mrd" in raw or "milliarden" in raw:
|
||||||
num *= 1000
|
num *= 1000
|
||||||
@@ -235,7 +233,6 @@ class WikipediaScraper:
|
|||||||
tokens = [token.strip() for token in infobox_text.split("|") if token.strip()]
|
tokens = [token.strip() for token in infobox_text.split("|") if token.strip()]
|
||||||
for i, token in enumerate(tokens):
|
for i, token in enumerate(tokens):
|
||||||
for field in field_names:
|
for field in field_names:
|
||||||
# Verwende "in", um Varianten und ambigue Unicode-Zeichen abzufangen.
|
|
||||||
if field.lower() in token.lower():
|
if field.lower() in token.lower():
|
||||||
j = i + 1
|
j = i + 1
|
||||||
while j < len(tokens) and not tokens[j]:
|
while j < len(tokens) and not tokens[j]:
|
||||||
@@ -269,7 +266,6 @@ class WikipediaScraper:
|
|||||||
debug_print(f"Extraktionsfehler: {str(e)}")
|
debug_print(f"Extraktionsfehler: {str(e)}")
|
||||||
return {'url': 'k.A.', 'first_paragraph': 'k.A.', 'branche': 'k.A.',
|
return {'url': 'k.A.', 'first_paragraph': 'k.A.', 'branche': 'k.A.',
|
||||||
'umsatz': 'k.A.', 'mitarbeiter': 'k.A.', 'full_infobox': 'k.A.'}
|
'umsatz': 'k.A.', 'mitarbeiter': 'k.A.', 'full_infobox': 'k.A.'}
|
||||||
|
|
||||||
@retry_on_failure
|
@retry_on_failure
|
||||||
def search_company_article(self, company_name, website):
|
def search_company_article(self, company_name, website):
|
||||||
search_terms = self._generate_search_terms(company_name, website)
|
search_terms = self._generate_search_terms(company_name, website)
|
||||||
@@ -290,6 +286,31 @@ class WikipediaScraper:
|
|||||||
continue
|
continue
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
# ==================== ALIGNMENT DEMO (Modus 3) ====================
|
||||||
|
def alignment_demo(sheet):
|
||||||
|
"""
|
||||||
|
Dieser Modus schreibt eine Demo-Zeile (z.B. in Zeile 11200) mit den neuen Spaltenüberschriften.
|
||||||
|
Passe die Liste new_headers an das gewünschte neue Schema an.
|
||||||
|
"""
|
||||||
|
# Beispiel für neue Spaltenüberschriften (bitte anpassen, falls das Schema anders lautet):
|
||||||
|
new_headers = [
|
||||||
|
"Re-Eval Flag", # z. B. Spalte A
|
||||||
|
"Firmenname", # Spalte B
|
||||||
|
"Website", # Spalte C
|
||||||
|
"Branche (Datenbank)",# Neue Spalte (grün)
|
||||||
|
"Branche Wikipedia", # Bestand
|
||||||
|
"Umsatz Wikipedia (Mio €)", # Bestand
|
||||||
|
"Mitarbeiter Wikipedia", # Bestand
|
||||||
|
"Erster Absatz Wikipedia", # Neu verschoben
|
||||||
|
"Wikipedia URL", # Bestand
|
||||||
|
"Datum der Extraktion", # Neu
|
||||||
|
"Version" # Neu
|
||||||
|
]
|
||||||
|
# Schreibe die neuen Header in Zeile 11200 (A11200 bis K11200)
|
||||||
|
header_range = "A11200:K11200"
|
||||||
|
sheet.update(values=[new_headers], range_name=header_range)
|
||||||
|
print("Alignment-Demo abgeschlossen: Neue Spaltenüberschriften in Zeile 11200 geschrieben.")
|
||||||
|
|
||||||
# ==================== DATA PROCESSOR ====================
|
# ==================== DATA PROCESSOR ====================
|
||||||
class DataProcessor:
|
class DataProcessor:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -298,6 +319,10 @@ class DataProcessor:
|
|||||||
def process_rows(self, num_rows=None):
|
def process_rows(self, num_rows=None):
|
||||||
if MODE == "2":
|
if MODE == "2":
|
||||||
print("Re-Evaluierungsmodus: Verarbeitung aller Zeilen mit 'x' in Spalte A.")
|
print("Re-Evaluierungsmodus: Verarbeitung aller Zeilen mit 'x' in Spalte A.")
|
||||||
|
elif MODE == "3":
|
||||||
|
print("Alignment-Demo-Modus: Schreibe Spaltenüberschriften in Zeile 11200.")
|
||||||
|
alignment_demo(self.sheet_handler.sheet)
|
||||||
|
return
|
||||||
else:
|
else:
|
||||||
start_index = self.sheet_handler.get_start_index()
|
start_index = self.sheet_handler.get_start_index()
|
||||||
print(f"Starte bei Zeile {start_index+1}")
|
print(f"Starte bei Zeile {start_index+1}")
|
||||||
@@ -347,8 +372,13 @@ class DataProcessor:
|
|||||||
|
|
||||||
# ==================== MAIN ====================
|
# ==================== MAIN ====================
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
mode_input = input("Wählen Sie den Modus: 1 für normalen Modus, 2 für Re-Evaluierungsmodus: ").strip()
|
mode_input = input("Wählen Sie den Modus: 1 für normalen Modus, 2 für Re-Evaluierungsmodus, 3 für Alignment-Demo: ").strip()
|
||||||
MODE = "2" if mode_input == "2" else "1"
|
if mode_input == "2":
|
||||||
|
MODE = "2"
|
||||||
|
elif mode_input == "3":
|
||||||
|
MODE = "3"
|
||||||
|
else:
|
||||||
|
MODE = "1"
|
||||||
if MODE == "1":
|
if MODE == "1":
|
||||||
try:
|
try:
|
||||||
num_rows = int(input("Wieviele Zeilen sollen überprüft werden? "))
|
num_rows = int(input("Wieviele Zeilen sollen überprüft werden? "))
|
||||||
|
|||||||
Reference in New Issue
Block a user