![]() |
PosExUltra - Ultimative Stringsuche/Parser
Wenn ihr schon immer mal eine Funktion gebraucht habt, die euch Webseiten und große Texte parsen/filtern/auslesen kann,
OHNE dass ihr ewig euch mit Pos und PosEx rumärgern müsst, dann hat eure Suche ein Ende! PS: Für Verbesserungen, optimierungen wären wir sehr Dankbar!
Delphi-Quellcode:
Erklärung:
{
* -------------------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" * YaNNiC und Novo schrieben diese Datei. Solange Sie diesen Vermerk nicht entfernen, * können Sie mit der Datei machen, was Sie möchten. Wenn wir uns eines Tages treffen * und Sie denken, die Datei ist es wert, können Sie mir dafür ein Bier ausgeben. * Wir hatten auf jeden Fall genug davon, als wir diese Funktion geschrieben haben :D * -------------------------------------------------------------------------------------- } procedure PosExUltra(source, searchwordbefore, searchwordafter, addbefore, addafter: string; continuesearch, reversesearch: boolean; liste: Tstringlist); var Anfang, Ende, Posi: Integer; Ergebnis: string; begin if reversesearch then begin //if reversesearch = true: if continuesearch then begin //if continuesearch = true: Ende := 0; while PosEx(searchwordafter, source, ende) > 0 do begin Anfang := PosEX(searchwordafter, source, Ende); Posi := Anfang; if Anfang > 0 then begin while (PosEX(searchwordbefore, source, Posi) = 0) or (PosEX(searchwordbefore, source, Posi) > Posi) do begin Dec(Posi); end; Ergebnis := Copy(source, Posi + length(searchwordbefore), Anfang - (Posi + length(searchwordbefore))); if (Ergebnis <> '') or (Ergebnis <> ' ') then liste.Add(addbefore + Ergebnis + addafter); Ende := Posi + length(searchwordbefore) + Length(Ergebnis) + Length(searchwordafter); end; end; end else //if continuesearch = false: begin Ende := 0; Anfang := PosEX(searchwordafter, source, Ende); Posi := Anfang; if Anfang > 0 then begin while (PosEX(searchwordbefore, source, Posi) = 0) or (PosEX(searchwordbefore, source, Posi) > Posi) do begin Dec(Posi); end; Ergebnis := Copy(source, Posi + length(searchwordbefore), Anfang - (Posi + length(searchwordbefore))); if (Ergebnis <> '') or (Ergebnis <> ' ') then liste.Add(addbefore + Ergebnis + addafter); end; end; end else //if reversesearch = false: begin if continuesearch then begin //if continuesearch = true: Ende := 0; Anfang := PosEX(searchwordbefore, source, Ende); while Anfang > 0 do begin Anfang := PosEX(searchwordbefore, source, Ende); if Anfang > 0 then begin Ende := PosEX(searchwordafter, source, Anfang); Ergebnis := Copy(source, Anfang + length(searchwordbefore), (Ende - Anfang) - length(searchwordbefore)); if (Ergebnis <> '') or (Ergebnis <> ' ') then liste.Add(addbefore + Ergebnis + addafter); Anfang := Anfang + length(Ergebnis); end; end; end else //if continuesearch = false: begin Ende := 0; Anfang := PosEX(searchwordbefore, source, Ende); if Anfang > 0 then begin Ende := PosEX(searchwordafter, source, Anfang); Ergebnis := Copy(source, Anfang + length(searchwordbefore), (Ende - Anfang) - length(searchwordbefore)); if (Ergebnis <> '') or (Ergebnis <> ' ') then liste.Add(addbefore + Ergebnis + addafter); end; end; end; end;
Code:
How To Use:
procedure PosExUltra(source, searchwordbefore, searchwordafter, addbefore, addafter: string; continuesearch, reversesearch: boolean; liste: Tstringlist);
In "source" befindet sich der große Text, den man Filtern möchte. "searchwordbefore" ist der Text, der sich VOR dem Wort was man will befindet. "searchwordafter" ist der Text, der sich NACH dem Wort was man will befindet. "addbefore" ist der Text, den man alternativ VOR dem GEFUNDENEN Wort anhängt. "addafter" ist der Text, den man alternativ NACH dem GEFUNDENEN Wort anhängt. "continuesearch": Es durchsucht den gesamten Text, wenn es MEHRERE Ergebnisse gibt (z.B. ALLE URLS), bei False bricht es nach dem 1. Fund ab. "reversesearch": Wenn "searchwordbefore" zu klein oder zu allgemein (zu oft vorkommend, oder gar variabel ist), dann sucht es erst nach "searchwordafter" und geht dann rückwärts, bis er "searchwordbefore" gefunden hat. Bsp: <ID=20>TEXT1<hierimmergleich> <ID=25>TEXT2<hierimmergleich> <ID=30>TEXT3<hierimmergleich> und man möchte alle!
Delphi-Quellcode:
Beispiele:
uses ... StrUtils;
public stringlist: TStringList; --- stringlist := TStringList.Create; source := 'groooßer Text mit Inhalt was ich will'; // wahlweise Absätze und Leerzeichen entfernen, um ein Besseres Ergenbis zu bekommen oder // weiteren Text zur Filterung zu erhalten: //source := StringReplace(source, ''#$A'', '', [rfReplaceAll]); //source := StringReplace(source, ''#13'', '', [rfReplaceAll]); //source := StringReplace(source, ' ', '', [rfReplaceAll]); //continue, reverse PosExUltra(source, 'VORDEMTEXT', 'NACHDEMTEXT', '', '', true, false, stringlist); stringlist.free; Einfache Vorwärtssuche bei eindeutigen Worten:
Delphi-Quellcode:
Man möchte alle URL Links, die mit .com aufhören haben:
source := '<text>DASWILLICH</text>';
PosExUltra(source, '<text>', '</text>', '', '', true, false, stringlist); //Suchwörter für Anfang und Ende sind leicht Filterbar, man kann vorwärts suchen.
Delphi-Quellcode:
Schwierige Stelle zum Suchen: Die Rückwärtssuche!
source := 'blatext xD [url]http://imagexxx.com[/url] und weiter text';
PosExUltra(source, 'http://', '.com', 'http://', '.com', true, false, stringlist); //Suchwörter für Anfang und Ende sind leicht Filterbar, man kann vorwärts suchen. //Da "http://" und ".com" abgeschnitten werden, fügen wir das dem gefundenen Wort nacher wieder an. Nehmen wir an, der Text wäre:
Code:
Der Anfangs und End Suchwert wäre:
source :=
<td>[url="?content=dictionary&task=term&dir=bla&ID=456"]DASWILLICH[/url]</td> <td style="line-height: 6pt;"> Anfang: '">' Ende: '</a></td>' Das würde nicht funktionieren, da Anfang SEHR häufig vorkommt. Also geht man zuerst so vor:
Delphi-Quellcode:
Das würde dann so aussehen:
source := StringReplace(source, ''#$A'', '', [rfReplaceAll]);
source := StringReplace(source, ''#13'', '', [rfReplaceAll]); source := StringReplace(source, ' ', '', [rfReplaceAll]);
Code:
nun kann man einfach die Rückwärtssuche bemühen, sie sucht zuerst nach Ende, und geht dann rückwärts bis er Anfang findet:
source := <td>[url="?content=dictionary&task=term&dir=bla&ID=456"]DASWILLICH[/url]</td><tdstyle="line-height:6pt;">
Delphi-Quellcode:
source := '<td>[url="?content=dictionary&task=term&dir=bla&ID=456"]DASWILLICH[/url]</td><tdstyle="line-height:6pt;">';
PosExUltra(source, '">', '</a></td><tdstyle="line-height:6pt', '', '', true, true, stringlist); Mfg Novo |
Re: PosExUltra - Ultimative Stringsuche/Parser
Sowas wie
Delphi-Quellcode:
bitte durch
if reversesearch = true then
Delphi-Quellcode:
ersetzen (die Gründe wurden schon oft im Forum erwähnt)
if reversesearch then
Und der Name ist definitiv verwirrend, denn gesucht wird hier nix, also nicht entsprechend des Funktionsergebnisses. StringReplaceUltra wäre da schon besser. |
Re: PosExUltra - Ultimative Stringsuche/Parser
Zitat:
Zitat:
Klar wird hier gesucht! ist sozusagen eine bessere PosEx -> PosExUltra :) |
Re: PosExUltra - Ultimative Stringsuche/Parser
Jupp, "StringReplace" wäre falsch. Es wird zwar nicht die Position zurückgegeben (also doch eher kein "PosEx"), aber es wird gesucht.
Zitat:
![]() Deine Funktion sieht viel versprechend aus bzw. was sie alles kann. Kannst du etwas über die Performance sagen, da du schreibst, sie sei für große Texte geeignet? Es gibt zahlreiche, schnelle Suchalgorithmen (Rabin-Karp & Co.), aber du verwendest keinen davon, wenn ich das richtig sehe. |
Re: PosExUltra - Ultimative Stringsuche/Parser
Das ist eine nette Funktion. Nenne sie doch lieber
Delphi-Quellcode:
Der Zusatz 'Ultra' erinnert so an Waschmittel.
Function PosEierlegendeWollmilchSau
Im Ernst: Was kann die Funktion, was ein TRegExpr nicht kann? |
Re: PosExUltra - Ultimative Stringsuche/Parser
Zitat:
Ein Beispiel: ![]() 800 Wörter -> Vorwärts -> SAUSCHNELL ( ja ich weis ist XML, dazu gibts ne XML Komponente, die bekomm ich aber partout nicht zum laufen :( FAIL ) ![]() Das gleiche mit ebenfalls 800 Wörter -> Rückwärtssuche nötig -> 30 Sekunden lang 25% CPU auslastung :D Sind aber schon heftig viele Zeilen. Wenn man z.B. Quellcode von Youtube parst, um die Video ID zu finden, ist das ruckzuck! Zitat:
|
Re: PosExUltra - Ultimative Stringsuche/Parser
Ich hätte aer noch was:
Delphi-Quellcode:
Dieses hat in soeiner Funktion besser nichts drin zu suchen.
Application.ProcessMessages;
|
Re: PosExUltra - Ultimative Stringsuche/Parser
Zitat:
|
Re: PosExUltra - Ultimative Stringsuche/Parser
Zitat:
|
Re: PosExUltra - Ultimative Stringsuche/Parser
Zitat:
Mal schaun, ob das denn funktioniert, bin mal weiter am Rumbasteln. Falls du es schon kannst, codeschnipsel :) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:51 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz