Nummernkreise für alle Produkte aus das Produktdatenblatt extrahiert. Fortna als Beispiel .xlsx unter examples dazu. create_examplex.py so impl., dass aus dem Sivas Export eine Liste der wirklich verbauten Produkte extrahiert werden kann, wenn man die cfg Produktnummern richtig pflegt
This commit is contained in:
+58
-28
@@ -81,19 +81,17 @@ def _extract_toc_numbers(doc) -> dict[str, str]:
|
||||
"""Extrahiert Kapitelnummern aus dem Inhaltsverzeichnis des PDFs.
|
||||
|
||||
Sucht TOC-Seiten (Seiten mit '....' Punkt-Fuellern) und ordnet
|
||||
Ueberschriftentexte ihren Kapitelnummern zu.
|
||||
Ueberschriftentexte ihren Kapitelnummern zu. Nur Eintraege mit
|
||||
expliziter Nummer werden erfasst (bis Level 2).
|
||||
|
||||
Returns:
|
||||
Dict title_text -> kapitelnummer, z.B. {"Typen von Weichen mit Bögen": "2.3.1"}
|
||||
Dict title_text -> kapitelnummer, z.B. {"Weichen Omniflo": "2.3"}
|
||||
"""
|
||||
import fitz
|
||||
|
||||
toc_entries: dict[str, str] = {}
|
||||
|
||||
for page_num in range(len(doc)):
|
||||
page = doc[page_num]
|
||||
text = page.get_text()
|
||||
# Nur TOC-Seiten verarbeiten (enthalten "....")
|
||||
if "...." not in text:
|
||||
continue
|
||||
|
||||
@@ -106,8 +104,7 @@ def _extract_toc_numbers(doc) -> dict[str, str]:
|
||||
if not line:
|
||||
continue
|
||||
|
||||
# TOC-Zeile: "Text ........... Seitennr"
|
||||
# Kapitelnummer steht oft auf separater Zeile davor
|
||||
# Kapitelnummer auf separater Zeile
|
||||
num_match = re.match(r"^(\d+(?:\.\d+)*)\s*$", line)
|
||||
if num_match:
|
||||
current_number = num_match.group(1)
|
||||
@@ -115,32 +112,59 @@ def _extract_toc_numbers(doc) -> dict[str, str]:
|
||||
|
||||
# Zeile mit Punkt-Fuellern = TOC-Eintrag
|
||||
dot_match = re.search(r"\.{4,}", line)
|
||||
if dot_match:
|
||||
# Text vor den Punkten extrahieren
|
||||
title = line[:dot_match.start()].strip()
|
||||
# Seitennummer nach den Punkten
|
||||
if title and current_number:
|
||||
toc_entries[title] = current_number
|
||||
current_number = ""
|
||||
elif title:
|
||||
# Nummer koennte am Anfang des Titels stehen
|
||||
nm = re.match(r"^(\d+(?:\.\d+)*)\s+(.+)", title)
|
||||
if nm:
|
||||
toc_entries[nm.group(2).strip()] = nm.group(1)
|
||||
if not dot_match:
|
||||
continue
|
||||
|
||||
# Auch inline Nummern: "1.4 Abkürzungen ..... 8"
|
||||
for line in lines:
|
||||
line = line.strip()
|
||||
dot_match = re.search(r"\.{4,}", line)
|
||||
if dot_match:
|
||||
title_part = line[:dot_match.start()].strip()
|
||||
nm = re.match(r"^(\d+(?:\.\d+)*)\s+(.+)", title_part)
|
||||
if nm:
|
||||
toc_entries[nm.group(2).strip()] = nm.group(1)
|
||||
title = line[:dot_match.start()].strip()
|
||||
if not title:
|
||||
continue
|
||||
|
||||
# Inline-Nummer am Anfang? "1.4 Abkürzungen ....."
|
||||
nm = re.match(r"^(\d+(?:\.\d+)*)\s+(.+)", title)
|
||||
if nm:
|
||||
toc_entries[nm.group(2).strip()] = nm.group(1)
|
||||
current_number = ""
|
||||
elif current_number:
|
||||
toc_entries[title] = current_number
|
||||
current_number = ""
|
||||
|
||||
return toc_entries
|
||||
|
||||
|
||||
RE_DATE = re.compile(r"^\d{2}\.\d{2}\.\d{4}$")
|
||||
RE_COPYRIGHT = re.compile(r"^Copyright\s+\d{4}", re.IGNORECASE)
|
||||
RE_VERSION_LINE = re.compile(r"^Version\s*[:.]?\s*\d", re.IGNORECASE)
|
||||
|
||||
# Bekannte Rausch-Muster: Autorinnen, Metadaten, Copyright-Zeilen
|
||||
_NOISE_KEYWORDS = {
|
||||
"annette schopper", "erstellt:", "freigabe:", "nicht freigegeben",
|
||||
"nur zur information", "schönenberger systeme gmbh",
|
||||
"justus-von-liebig-str", "info@schoenenberger.de",
|
||||
"www.schoenenberger.de",
|
||||
}
|
||||
|
||||
|
||||
def _is_noise(text: str) -> bool:
|
||||
"""Erkennt Rausch-Zeilen die nicht ins RST gehoeren."""
|
||||
lower = text.lower().strip()
|
||||
if RE_COPYRIGHT.match(text):
|
||||
return True
|
||||
if RE_DATE.match(text.strip()):
|
||||
return True
|
||||
if RE_VERSION_LINE.match(text):
|
||||
return True
|
||||
for kw in _NOISE_KEYWORDS:
|
||||
if kw in lower:
|
||||
return True
|
||||
# Seitenzahlen
|
||||
if re.match(r"^Seite\s+\d+$", text, re.IGNORECASE):
|
||||
return True
|
||||
# Einzelne kurze Jahreszahlen mit Autorin: "2020 Annette Schopper"
|
||||
if re.match(r"^\d{4}\s+[A-Z][a-z]+\s+[A-Z][a-z]+$", text):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def extract_text_to_rst(pdf_path: Path, rst_path: Path) -> int:
|
||||
"""Extrahiert Text aus PDF und schreibt ihn als .rst.
|
||||
|
||||
@@ -188,6 +212,8 @@ def extract_text_to_rst(pdf_path: Path, rst_path: Path) -> int:
|
||||
text = text.strip()
|
||||
if not text:
|
||||
continue
|
||||
if _is_noise(text):
|
||||
continue
|
||||
|
||||
raw_lines.append({
|
||||
"text": text,
|
||||
@@ -311,6 +337,10 @@ def extract_text_to_rst(pdf_path: Path, rst_path: Path) -> int:
|
||||
# Mehrfache Leerzeilen reduzieren
|
||||
rst = "\n".join(rst_lines)
|
||||
rst = re.sub(r"\n{3,}", "\n\n", rst)
|
||||
# 9-stellige Nummern mit Leerzeichen zusammenfuegen: "834 372 007" -> "834372007"
|
||||
rst = re.sub(r"\b(\d{3})\s(\d{3})\s(\d{3})\b", r"\1\2\3", rst)
|
||||
rst = re.sub(r"\b(\d{3})\s(\d{6})\b", r"\1\2", rst)
|
||||
rst = re.sub(r"\b(\d{6})\s(\d{3})\b", r"\1\2", rst)
|
||||
rst = rst.strip() + "\n"
|
||||
|
||||
rst_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
Reference in New Issue
Block a user