"Christmas - the time to fix the computers of your loved ones" « Lord Wyrm

Perl RE Tipp in PHP gesucht

Rektal 11.08.2005 - 16:05 670 10
Posts

Rektal

Here to stay
Registered: Dec 2002
Location: Inside
Posts: 4452
Ich moechte bei folgender RE

/(word_is_long|word|anotherone|another)/

das nicht der kleinste macht zuerst trifft, sondern der laengste.

Ich habs probiert mit dem '?' Operator, z.B.

/((word_is_long)?|(word)?|(anotherone)?|(another)?)/

funktioniert auch, geht aber auf die Performance zu sehr. Die Texte sind durchschnittlich 6kb lang und es werden 50 davon Pro Seite verarbeitet, macht also 300kb.

Ich dachte es muesste mit dem /U modifier auch gehen, hat aber nicht funktioniert.

/(word_is_long|word|anotherone|another)/?

Ich versuche damit einen Text zu splitten und die gematchten Woerter zu highlighten (a.k.a Suchmaschine ergebnis word highlight).

Any ideas? Oder andere Methoden? Problem ist, dass ein und das selbe Wort, nur in Unterschiedlicher Laenge, vorkommt.
Bearbeitet von Rektal am 26.08.2005, 16:11

watchout

Legend
undead
Avatar
Registered: Nov 2000
Location: Off the grid.
Posts: 6845
aaalso... eigentlich solltest du die "greedyness" ausnutzen können indem du... /(word(_is_long)?)|(another(one)?)/ machst - das is aber untested ;)

Rektal

Here to stay
Registered: Dec 2002
Location: Inside
Posts: 4452
Funktioniert leider auch nicht.

Aber, vielleicht geh ich das ganze auch falsch herum an. Jemand andere Ideen um ausgewaehlte woerter in einem text zu highlighten?

Es geht im wesentlichen nur um das Einfuegen von <strong> Tags um die gesuchten Woerter und um die Position des ersten gesuchten Wortes, damit man ein entsprechendes Excerpt anzeige kann.

Ich brauche keine Gewichtung der Relevanz der einzelnen Suchwoerter innerhalb des Textes.

watchout

Legend
undead
Avatar
Registered: Nov 2000
Location: Off the grid.
Posts: 6845
hast du probiert mit ungreedy-modifier?
die ?'s bewirken ja ne umkehr, also müsstest du das ganze nochmal umdrehen, dann sollte es eigentlich theoretisch vielleicht unter umständen gehen :D

that

Moderator
Hoffnungsloser Optimist
Avatar
Registered: Mar 2000
Location: MeidLing
Posts: 11338
Du könntest den Text nach Wortgrenzen splitten und dann jedes isolierte Wort mit deiner Liste vergleichen.

Rektal

Here to stay
Registered: Dec 2002
Location: Inside
Posts: 4452
@watchout: ja hab ich, keine Veraenderung sichtbar.

@that: meinst du split nach /\s+/, foreach ueber die elemente und $array[$i] = "<strong>{$array[$i]}</strong>" wo ein Match ist? Vielleicht kann ich den Match dann ja vereinfachen, muss ich mir anschauen. Danke fuer den Tipp

gue

Addicted
Avatar
Registered: Feb 2003
Location: Linz
Posts: 400
Wenn ich das jetzt richtig verstanden habe, würde aber in deinem Fall auch ein einfaches str_replace reichen (ist auch viieeeeel performanter). Einfach die Suchwörter nach länge sortieren und dann im Text str_replacen. Dadurch kriegst du zwar Sachen wie <strong><strong>another</strong>one</strong> aber is ja wurscht, oder? Ahja: fürs Suchwort "strong" musst du dir dann was anderes einfallen lassen :)
Wenn in dem Text URLs vorkommen (z.B. bei einem Forumtext) ist das ganze noch ein bisschen blöder. Mangels einer anderen Lösung hab ich mir da selbst einen Scanner geschrieben, der auch die Ersetzungen vornimmt. Da wärs aber vielleicht am besten, du schaust dir die Lösungen von z.B. PHPBB an.

Rektal

Here to stay
Registered: Dec 2002
Location: Inside
Posts: 4452
Ok, also ich weiss natuerlich das str_replace performanter ist. Es hat schon einen Grund gegeben, dass ich es nicht genommen habe, ich weiss es jetzt aber selber nicht mehr ;)

Der Text hat definitiv keine URLs weil es eine Text-Only repraesentation von jeglicher Art Dokument ist, also bei HTMl wird nur der Text des Links usw. angezeigt. Somit kein Problem mit str_replace. Insofern waere eine Mehrverschachtelung von Strong in erster Instanz auch kein Problem. Ich will im Endeffekt schon "semantisch korrekt [tm]" bleiben, aber das kann ich fuers erste ja ignorieren.

Warum ich bisher eigentlich nur mit preg_split/replace gearbeitet hab, war einerseits das Verschachtelungsproblem und andererseits muss ich auch wissen, wo das erste Wort gefunden wurde. Ich zeige ja nicht den ganzen Text an sondern nur die Relevanten Teile mit den Suchwoertern (wobei ich es hier einfach mache und nur ab dem ersten gefundenen den Text fuer eine bestimmte Anzahl von Zeichen ausgebe).

Also was ich bisher in PHP probiert habe, das mir ein technisch schoenes Ergebnis geliefert hat, geht auf die Performance. Fuer einen Request kein Problem, aber Suchen werden sehr stark beansprucht, darum muss es auch unter Last optimal laufen.

Wenn ich mich dunkel erinnere werden bei den "Grossen" die Frontends entsprechend optimiert geschrieben (c++), mir steht aber PHP und maximal noch Java zur Verfuegung (auch nicht grad als Performance-Bringer bekannt ...)

gue

Addicted
Avatar
Registered: Feb 2003
Location: Linz
Posts: 400
Also nur so eine Idee: Wenn du sowieso nur vom ersten gefundenen einen Teil ausgibst, kannst du ja die Position von dem stripos()en, dann den relevanten Teil heraussubstr()en und bei diesem dann preg_replace()n, str_ireplace()n oder was auch immer - dann sollte das auch bei großen Datenmengen halbwegs schnell funktionieren. Naja aber vielleicht sollte sich das noch wer durchdenken, der nicht einen Riesenkater im Kopf hat... :mad:

Rektal

Here to stay
Registered: Dec 2002
Location: Inside
Posts: 4452
An sowas dachte ich auch, aber wieder verworfen, weil ich ja nicht stripos von einem Keywort sondern von mehrere brauche. Aber ja, ist wahrscheinlich schon schneller. stripos ueber alle keywords aus dem array und ueber das anzuzeigende Fenster mach ich dann den preg_replace. Werds nachm WE testen und feedbacken.

Btw, generell gefragt, wsa nehmt ihr zum indizieren von Seiten und Ausgabe?

Ich hab bisher phpdig verwendet, bin aber unzufrieden mit den Ergebnissen. Auch das crawlen mit phpdig hat ewig gedauert und er hat zumindest damals nur HTMl indiziert und nicht andere Dokumente (PDF). Verwende derzeit noch einene eigenen Crawler zusammen mit Lucene als Indexsucher. Ausgabe in PHP.

Rektal

Here to stay
Registered: Dec 2002
Location: Inside
Posts: 4452
Ich hab das mit perl re jetzt geschmissen, es war sowie alles zulangsam. Ich hab dann noch ein Modul fuer Lucene gefunden, dass direkt vom QueryParser die Tokens nimmt und das Excerpt bildet (http://lucene.apache.org/java/docs/lucene-sandbox/ bzw. http://svn.apache.org/repos/asf/luc...ib/highlighter/ )
Kontakt | Unser Forum | Über overclockers.at | Impressum | Datenschutz