Textmustererkennung

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
Joh
Lazarusforum e. V.
Beiträge: 383
Registriert: Sa 26. Mai 2012, 17:31
OS, Lazarus, FPC: Win 10 (L 2.2.6 x64 FPC 3.2.2)
CPU-Target: 64Bit

Textmustererkennung

Beitrag von Joh »

Moin,

ich habe hier eine Menge an Textdateien... (letztlich ein Extrakt aus pdf-Dateien).

Nun haben diese Dateien alle mitten im Text wiederkehrende Merkmale (Footer, Seitenumbruch, Header), die ich löschen muss.
Beispiel:
<FLIEßTEXT>
Änderungsdatum: 02.12.2022 Version: 4.2
Druckdatum: 11.12.2025
BlaBla DE-DE - AB1005910 Seite 1/10
<SEITENUMBRUCH>Firmy AB
Produktname: Eisenoxid XY
<FLIEßTEXT>
Die Anzahl der Header- und Footerzeilen sind dabei natürlich variabel, aber innerhalb eines Dokumentes gleich.

Mein Problem dabei:
wie kann ich Konstrukte wie 'Seite 1/10', '2 (12)', '(Fortsetzung von Seite 3)' als wiederkehrend herausfinden, ohne Regex zu benutzen (oder KI)?
Oder: wie kann ich Regex dazu benutzen, diese Zeilen als Header/Footer zu erkennen?

PS: Ist meine grundsätzliche Idee, die Datei in eine Stringliste einzulesen, den 1. Seitenumbruch zu finden (steht immer an Pos. 1 der Zeile) und die Zeilen davor und dahinter mit denen des 2. (bis x-ten) Seitenumbruchs zu vergleichen sinnvoll?
just my two Beer

Benutzeravatar
Zvoni
Beiträge: 698
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz/FPC fixes)
CPU-Target: 64Bit
Wohnort: BW

Re: Textmustererkennung

Beitrag von Zvoni »

Joh hat geschrieben: Mi 10. Jun 2026, 07:06 *schnipp*
Oder: wie kann ich Regex dazu benutzen, diese Zeilen als Header/Footer zu erkennen?

PS: Ist meine grundsätzliche Idee, die Datei in eine Stringliste einzulesen, den 1. Seitenumbruch zu finden (steht immer an Pos. 1 der Zeile) und die Zeilen davor und dahinter mit denen des 2. (bis x-ten) Seitenumbruchs zu vergleichen sinnvoll?
Sowas?
https://regex101.com/r/UbI2c8/2
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

Joh
Lazarusforum e. V.
Beiträge: 383
Registriert: Sa 26. Mai 2012, 17:31
OS, Lazarus, FPC: Win 10 (L 2.2.6 x64 FPC 3.2.2)
CPU-Target: 64Bit

Re: Textmustererkennung

Beitrag von Joh »

Da hast du mich Mißverstanden...
Es geht nicht um genau diese drei Beispiele, sondern darum, das Strings mit fortlaufenden Nummern als gleich erkannt werden sollen.

Ich habe 8000 Dateien von ca. 1000 Herstellern, die alle unterschiedliche Header/Footer haben, die ich entfernen muß.

Dabei ist in den meisten Fällen eine der Zeilen mit einer Seitenzahl versehen, die ich mit löschen muß.
just my two Beer

Benutzeravatar
Zvoni
Beiträge: 698
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz/FPC fixes)
CPU-Target: 64Bit
Wohnort: BW

Re: Textmustererkennung

Beitrag von Zvoni »

Joh hat geschrieben: Mi 10. Jun 2026, 14:52 Da hast du mich Mißverstanden...
Es geht nicht um genau diese drei Beispiele, sondern darum, das Strings mit fortlaufenden Nummern als gleich erkannt werden sollen.

Ich habe 8000 Dateien von ca. 1000 Herstellern, die alle unterschiedliche Header/Footer haben, die ich entfernen muß.

Dabei ist in den meisten Fällen eine der Zeilen mit einer Seitenzahl versehen, die ich mit löschen muß.
AUTSCH.
Da wird dir aber mMn das mit "fortlaufender" Nummer nicht wirklich weiterhelfen.
Hast keinen anderen Identifier?
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

Joh
Lazarusforum e. V.
Beiträge: 383
Registriert: Sa 26. Mai 2012, 17:31
OS, Lazarus, FPC: Win 10 (L 2.2.6 x64 FPC 3.2.2)
CPU-Target: 64Bit

Re: Textmustererkennung

Beitrag von Joh »

Wie gesagt: das einzige, was ich weiß, ist: es existieren x Seitenumbrüche.
Es sind meistens zwischen 10 und 20 Seiten.
Die Texte aus den pdf-Seiten habe ich extrahiert.

Und ich weiß: Die Zeilen vor und hinter den Seitenumbrüchen sich gleich: Footer davor und Header (der nächsten Seite danach).
Wie viele Zeilen Footer und Header lang sind, weiß ich nicht, das ist Hersteller- oder Dokumentenabhängig.

Aber fast jedes Dokument enthält eine Zeile, in der die Seitennummer steht, diese kann auch weitere Ziffern enthalten, in einem meiner Beispieldateien steht z.B.:
Ausgabedatum/Überarbeitungsdatum : 19/02/2025 Datum der letzten Ausgabe : 09/01/2025 Version : 3.2 1/16
wobei 1/16 die Seitennummer ist...

Schlimmstenfalls muß ich halt nach dieser Zahl suchen, ich weiß ja auch, das im Footer vor dem 6. Zeilenumbruch die Zahl 6 auftauchen kann ... Aber genau das händisch zu programmieren würde ich mir gerne ersparen.


Das ganze ist mal wieder Wasser auf meine Mühle: das, was der Mensch automatisch auf einen Blick erkennt ist oft schwierig zu programmieren und das was in der Software einfach aussieht überblickt der Mensch kaum mehr.
just my two Beer

Epcop
Beiträge: 168
Registriert: Di 29. Mai 2012, 09:36

Re: Textmustererkennung

Beitrag von Epcop »

Wenn das Wort "Seite" mit drin steht, könnte man vorher in einer Schleife sämtliche Möglichkeiten durchgehen, dass dann fest einlesen und ersetzen.

Code: Alles auswählen

Schlimmstenfalls muß ich halt nach dieser Zahl suchen,
1/16 - wäre ich vorsichtig. Da müsstest du wirklich dann sicher gehen, wenn dass das dann wirklich immer am Seitenende ist. Weil 1/16 kann ja auch sonst im Dokument auftauchen.

Und wenn es immer am Seitenende ist, könnte man evtl. damit arbeiten.

Joh
Lazarusforum e. V.
Beiträge: 383
Registriert: Sa 26. Mai 2012, 17:31
OS, Lazarus, FPC: Win 10 (L 2.2.6 x64 FPC 3.2.2)
CPU-Target: 64Bit

Re: Textmustererkennung

Beitrag von Joh »

nee nee...
das ist in diesem Dokument genau in der Zeile
<SEITENUMBRUCH> -2 (in diesem Dokument) der Fall.

Das kann ich so schon lokalisieren.

Aber Dazu müßte ja erstmal geklärt werden, das in dieser Zeile
Ausgabedatum/Überarbeitungsdatum : 19/02/2025 Datum der letzten Ausgabe : 09/01/2025 Version : 3.2 1/16
das rote das Literal und die schwarze 1 die Variable ist.

Einen Seitenumbruch später sehe ich dann ja, das in der Zeile <SEITENUMBRUCH> -2 steht:
Ausgabedatum/Überarbeitungsdatum : 19/02/2025 Datum der letzten Ausgabe : 09/01/2025 Version : 3.2 2/16

Das erkennt mein Visuelles System auf den ersten Blick als Analogie, aber mein programmiertechnisches ich sucht nach einem Algorithmus, der das erkennt.

PS: der Original-String des o.g. Beispiels mit Leerzeichen lautet:
Beispiel.png
Beispiel.png (7.18 KiB) 562 mal betrachtet
dooferweise werden in manchen Seiten weniger/mehr Leerzeichen angezeigt... (ich befürchte Word)
FF=<Seitenumbruch>
just my two Beer

Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 454
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Re: Textmustererkennung

Beitrag von Jorg3000 »

Moin!
Hier mein Vorschlag ...
Um eine Zeile mit Seitenzahl zu finden, wird die Zeile zeichenweise durchlaufen und dabei geprüft, in welchem Bereich (Leerzeichen,ErsteZahl,Strich,ZweiteZahl) man sich gerade befindet.
Wenn man am Zeilenende ohne Störung den Bereich=ZweiteZahl erreicht hat, ist es eine Zeile mit korrekter Seitenzahl.

Code: Alles auswählen

function istZeileMitSeitenzahl(const s: String): Boolean;
var i, p: SizeInt;
    Bereich: (Leerzeichen,ErsteZahl,Strich,ZweiteZahl);
begin
  Result:=false;
  p:=Pos(' Seite ',s);
  if p<=0 then Exit;

  Bereich:=Leerzeichen; // Position p+6 ist das Leerzeichen hinter "Seite"

  for i:=p+6 to Length(s) do
    begin
     CASE s[i] OF
      #32: begin
            if Bereich in [ErsteZahl,Strich] then Exit;  // FALSE weil innerhalb "1/16" kein Leerzeichen erwartet
            Bereich:=Leerzeichen;
           end;
      '/': begin
            if Bereich<>ErsteZahl then Exit;  // // FALSE weil "/" nur hinter erster Zahl erwartet
            Bereich:=Strich;
           end;
      '0'..'9': begin
            if not (Bereich in [Leerzeichen,ErsteZahl,Strich,ZweiteZahl]) then Exit;
            if Bereich in [Leerzeichen,Strich] then inc(Bereich); // => jetzt ErsteZahl oder ZweiteZahl
           end;
      ELSE Exit;  // keine Buchstaben o.ä. mehr erlaubt
     END;
    end;

  Result:=(Bereich=ZweiteZahl);
end;


procedure durchlaufeText(const txt: String);
var y: Integer;
    sl: TStringList;
begin
  sl:=TStringList.Create;
  sl.Text:=txt;
  for y:=0 to sl.Count-1 do
    begin
     if istZeileMitSeitenzahl(sl[y]) then ShowMessage(sl[y]);
    end;
  sl.Destroy;
end;


procedure TForm1.Button1Click(Sender: TObject);
begin
  durchlaufeText('Hallo Seite 1 NICHT 16'#13'Hier Seite 1/10'#10'Tschüss Seite 2/15 DOCH NICHT'#13);  // #10=FormFeed
end; 
EDIT: Habe "CASE ... ELSE Exit;" hinzugefügt.
Grüße, Jörg

Joh
Lazarusforum e. V.
Beiträge: 383
Registriert: Sa 26. Mai 2012, 17:31
OS, Lazarus, FPC: Win 10 (L 2.2.6 x64 FPC 3.2.2)
CPU-Target: 64Bit

Re: Textmustererkennung

Beitrag von Joh »

@Jorg: Danke für die Idee...

aber

Ich bin heute morgen aufgewacht, döste im Bett so vor mich hin...

Da kam der Gedankenblitz:

Code: Alles auswählen

i)   alle Seitenumbrüche merken
ii)  in Schleife checken, ob Zeilen Gleich sind => wenn gleich: Kopf/Fußzeile
iii) ist Zeile[i] nicht gleich:
     ersetze in der Zeile auf Seite 1 alle "1" und "2" durch Leerzeichen
     ersetze in der Zeile auf Seite 2 alle "1", "2" und "3" durch Leerzeichen
     ersetze in der Zeile auf Seite 3 alle "2", "3" und "4" durch Leerzeichen
     ...
     ersetze in der Zeile auf Seite i alle "i-1", "i" und "i+1" durch Leerzeichen

     checken, ob Zeilen Gleich sind => wenn gleich: Kopf/Fußzeile
iv) wenn nicht gleich: Kopf/Fußzeile zu Ende
auf der i-ten Seite steht ja entweder Seite (i)
oder im Header: Fortsetzung von Seite (i-1)
oder im Footer: Fortsetzung auf Seite (i+1)

auf der 1. Seite wird der Header nicht gecheckt, da der nicht im Bereich des Seitenumbruchs liegt
auf der letzten Seite wird der Footer nicht gecheckt, da der nicht im Bereich des Seitenumbruchs liegt

Klingt nach KISS-Prinzip

oder nach af: Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen

jetzt muß es nur noch funktionieren ;-) (und programmiert werden)
just my two Beer

Benutzeravatar
Zvoni
Beiträge: 698
Registriert: Fr 5. Jul 2024, 08:26
OS, Lazarus, FPC: Windoof 10 Pro (Laz/FPC fixes)
CPU-Target: 64Bit
Wohnort: BW

Re: Textmustererkennung

Beitrag von Zvoni »

Joh hat geschrieben: Do 11. Jun 2026, 09:24 @Jorg: Danke für die Idee...

aber

Ich bin heute morgen aufgewacht, döste im Bett so vor mich hin...

Da kam der Gedankenblitz:

Code: Alles auswählen

i)   alle Seitenumbrüche merken
ii)  in Schleife checken, ob Zeilen Gleich sind => wenn gleich: Kopf/Fußzeile
iii) ist Zeile[i] nicht gleich:
     ersetze in der Zeile auf Seite 1 alle "1" und "2" durch Leerzeichen
     ersetze in der Zeile auf Seite 2 alle "1", "2" und "3" durch Leerzeichen
     ersetze in der Zeile auf Seite 3 alle "2", "3" und "4" durch Leerzeichen
     ...
     ersetze in der Zeile auf Seite i alle "i-1", "i" und "i+1" durch Leerzeichen

     checken, ob Zeilen Gleich sind => wenn gleich: Kopf/Fußzeile
iv) wenn nicht gleich: Kopf/Fußzeile zu Ende
auf der i-ten Seite steht ja entweder Seite (i)
oder im Header: Fortsetzung von Seite (i-1)
oder im Footer: Fortsetzung auf Seite (i+1)

auf der 1. Seite wird der Header nicht gecheckt, da der nicht im Bereich des Seitenumbruchs liegt
auf der letzten Seite wird der Footer nicht gecheckt, da der nicht im Bereich des Seitenumbruchs liegt

Klingt nach KISS-Prinzip

oder nach af: Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen

jetzt muß es nur noch funktionieren ;-) (und programmiert werden)
Ausgabedatum/Überarbeitungsdatum : 19/02/2025 Datum der letzten Ausgabe : 09/01/2025 Version : 3.2 1/16
und wenn du die 1, 2, ...i+1 durch blanks ersetzt, zerlegst du das Datum, die Version.... und was weiss ich noch alles

Hmm....Vielleicht per Levenshtein die Zeilen jeweils vor einem Umbruch miteinander vergleichen (also im Prinzip die "Footer" miteinander vergleichen).
Ich glaube mit Levenshtein könntest du da was erreichen, wenn der Unterschied zwischen zwei (und mehr) Footern, nur eine Seitenzahl ist, der Rest aber konstant gleich.

Beispiel:
Die Levenshtein-Distanz zwischen dem Footer auf Seite 1 und dem Footer auf Seite 2 sollte eigentlich theoretisch 1 sein, weil sich ja nur die Seitenzahl unterscheidet.
Zwischen Footer Seite 9 und Footer Seite 10 müsste es dann 2 sein.
usw. usf.
Siehe auch:
https://de.wikipedia.org/wiki/Levenshtein-Distanz
https://wiki.freepascal.org/Levenshtein_distance

Heisst: Bei einem Dokument mit 99 Seiten kannst du davon ausgehen, dass die Distanz zwischen zwei Footern maximal 2 sein müsste

ggf. mit Headern dasselbe
Ein System sie alle zu knechten, ein Code sie alle zu finden,
Eine IDE sie ins Dunkel zu treiben, und an das Framework ewig zu binden,
Im Lande Redmond, wo die Windows drohn.

pluto
Lazarusforum e. V.
Beiträge: 7201
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Textmustererkennung

Beitrag von pluto »

Joh hat geschrieben:Ausgabedatum/Überarbeitungsdatum
Ist das immer gleich? Wenn ja ist der "rest einfach. Das finden und bis zum letzten Zeichen der seite alle löschen.
Die Daten dazwischen zu extrahieren, ist auch nicht so schwer.... Ein Datum erkennst du am /.
Sind die PDF Dateien "geheim?" oder kannst du ein paar Bilder zeigen z.b. von den unteren Seiten aus verschiedenen Dokumenten?
MFG
Michael Springwald

Antworten