PHP Glossar-Parser Herausforderung für Profis
Euer Webmaster braucht mal ein wenig Hilfe
Hi, heute habe ich mal eine kleine Aufgabe für PHP Profis.
Für unser Glossar auf administrator.de brauche ich einen performanten Glossar-Parser.
Folgendes Szenario bzw. Variablen bestehen (vereinfacht):
$content
Die Inhalte von "$content" liegt im "htmlentities($content, ENT_QUOTES);" Format vor (aus Sicherheitsgründen, damit kein HTML interpretiert wird). Die HTML-Tags wie <img.. > oder <a href..> kommen zunächst von unserem Format-Parser. Danach soll der Glossar-Parser starten. Er darf HTML-Tags also nicht berücksichtigen. Die Variable "$content" kann bis zu 10.000 Wörter fassen.
$glossar_arr
Das Array "$glossar_arr" kann aus mehr als 10.000 Begriffen bestehen. Der erste Wert ist der Glossar-Begriff, der zweite die ID. Der Glossar-Link zum Aufruf lautet dann z.B.: /index.php?mod=glossar&idx=2
Ich suche jetzt eine Abfrage, eine RegExp oder sonstige PHP Lösung, die sehr performant den Inhalt in "$content" durchsucht und die zutreffenden Glossar-Begriffe aus dem Array (wie im Beispiel "Internet", "Server", etc.) mit dem Link markiert bzw. den Begriff durch den Link plus Begriff ersetzt.
Natürlich dürfen die HTML-Tags wie <img ..> oder <a href..> nicht berücksichtigt werden (z.B. darf im Link "title="-Tag der Glossar-Parser nicht greifen, am besten alle HTML-Tags excluden). Auch sollen nur ganze Wörter und keine Teilbegriffe gefunden werden.
Für eine Lösung wäre ich sehr dankbar
P.S. Ich poste meine bisherige Lösung extra nicht, um neue Ideen und einen neuen Ansatz zu finden. Meine Lösung ist bisher zu langsam.
Gruß
Frank
Webmaster
Für unser Glossar auf administrator.de brauche ich einen performanten Glossar-Parser.
Folgendes Szenario bzw. Variablen bestehen (vereinfacht):
$content = "Das ist jetzt der Text der Mitglieder mit Glossar-Begriffen wie Server oder Internet. Umlaute wie ö oder ß sind mit htmlentities umgewandelt. Das TCP/IP Protokoll oder den Begriff Firewall sollen mit einem Glossar-Link markiert werden. Der Text hat aber auch <a href=\"/index.php?content=Serverprobleme_im_Internet.html\" titel=\"Server und Internet Probleme\">Links</a> oder Images <img src=\"/images/articles/server.jpg\" alt=\"\" /> die nicht interpretiert werden dürfen.";
$glossar_arr = array(array("Internet","2"), array("Server","3"), array("Firewall","4"), array("TCP/IP","5"), array("etc.","id"));
$content
Die Inhalte von "$content" liegt im "htmlentities($content, ENT_QUOTES);" Format vor (aus Sicherheitsgründen, damit kein HTML interpretiert wird). Die HTML-Tags wie <img.. > oder <a href..> kommen zunächst von unserem Format-Parser. Danach soll der Glossar-Parser starten. Er darf HTML-Tags also nicht berücksichtigen. Die Variable "$content" kann bis zu 10.000 Wörter fassen.
$glossar_arr
Das Array "$glossar_arr" kann aus mehr als 10.000 Begriffen bestehen. Der erste Wert ist der Glossar-Begriff, der zweite die ID. Der Glossar-Link zum Aufruf lautet dann z.B.: /index.php?mod=glossar&idx=2
Ich suche jetzt eine Abfrage, eine RegExp oder sonstige PHP Lösung, die sehr performant den Inhalt in "$content" durchsucht und die zutreffenden Glossar-Begriffe aus dem Array (wie im Beispiel "Internet", "Server", etc.) mit dem Link markiert bzw. den Begriff durch den Link plus Begriff ersetzt.
Natürlich dürfen die HTML-Tags wie <img ..> oder <a href..> nicht berücksichtigt werden (z.B. darf im Link "title="-Tag der Glossar-Parser nicht greifen, am besten alle HTML-Tags excluden). Auch sollen nur ganze Wörter und keine Teilbegriffe gefunden werden.
Für eine Lösung wäre ich sehr dankbar
P.S. Ich poste meine bisherige Lösung extra nicht, um neue Ideen und einen neuen Ansatz zu finden. Meine Lösung ist bisher zu langsam.
Gruß
Frank
Webmaster
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-Key: 89698
Url: https://administrator.de/contentid/89698
Ausgedruckt am: 28.03.2024 um 22:03 Uhr
10 Kommentare
Neuester Kommentar
Hallo Frank!
Hast du schon mit preg_replace bzw. str_replace ausprobiert?
Also dass es z.B. so aussehen könnte:
Auch eine Lösung wär auch das du das mit einer while funktion machst:
mfg
masterG
Hast du schon mit preg_replace bzw. str_replace ausprobiert?
Also dass es z.B. so aussehen könnte:
<?php
$content = str_replace("Internet","<a href="glossar.php">Internet</a>", $content);
?>
<?php
mysql_connect("localhost","root","");
mysql_select_db("db");
$sql = "SELECT ID, titel FROM glossar;";
$result = mysql_query($sql);
while($row = mysql_fetch_array($result) or die(mysql_error()))
{
$content = str_replace($row['titel'],"<a href=glossar.php?idx=".$row['ID'].">".$row['titel']."</a>", $content);
}
?>
masterG
Hi Frank,
wie hast du es mit den Formatierungsmöglichkeiten gelöst?! Da wirst du doch auch sicher REGEX verwendet haben, oder?
Ansonsten gehen mir 2 Ideen gerade durch den Kopf (erfährst du später mehr)....mit was ich mir ein bisschen schwer tu, ist der Faktor "Leistungsaufwand der MySQL". Wie hälst du die 10.000 Begriffe immer im PHP? Hast du ne $_SESSION Array gebildet oder wie darf ich mir das vorstellen. Denn wir reden hier ja grad nicht über ne 0815 Datenbank.
Gruss,
Dani
wie hast du es mit den Formatierungsmöglichkeiten gelöst?! Da wirst du doch auch sicher REGEX verwendet haben, oder?
Ansonsten gehen mir 2 Ideen gerade durch den Kopf (erfährst du später mehr)....mit was ich mir ein bisschen schwer tu, ist der Faktor "Leistungsaufwand der MySQL". Wie hälst du die 10.000 Begriffe immer im PHP? Hast du ne $_SESSION Array gebildet oder wie darf ich mir das vorstellen. Denn wir reden hier ja grad nicht über ne 0815 Datenbank.
Gruss,
Dani
Ich verstehe den aktuellen Zustand sehr wohl, jedoch würde ich zu einer anderen Lösung ansetzen.
Anstelle die Glossar-Links jedesmal on-the-fly zu generieren, würde ich diese bereits beim in-die-Datenbank-schreiben setzen lassen.
Hat einzig und alleine den Nachteil, daß wenn ein Begriff wegfällt, die ganze DB aktualisiert werden müßte.
(ob dies jemals vorkommt, weiß ich allerdings nicht...)
Der Regex ist sicherlich ein wenig komplexer, aber ich denke, Du wirst mit Sicherheit schon den performantesten haben.
Regex bedeutet immer rechenintensiv, weil er ausgewertet werden muß.
Die o.g. Lösung wird einfach nur ausgespuckt, und auch die Aktualisierung der DB liese sich in 1-2 Tagen komplett realisieren
Lonesome Walker
Anstelle die Glossar-Links jedesmal on-the-fly zu generieren, würde ich diese bereits beim in-die-Datenbank-schreiben setzen lassen.
Hat einzig und alleine den Nachteil, daß wenn ein Begriff wegfällt, die ganze DB aktualisiert werden müßte.
(ob dies jemals vorkommt, weiß ich allerdings nicht...)
Der Regex ist sicherlich ein wenig komplexer, aber ich denke, Du wirst mit Sicherheit schon den performantesten haben.
Regex bedeutet immer rechenintensiv, weil er ausgewertet werden muß.
Die o.g. Lösung wird einfach nur ausgespuckt, und auch die Aktualisierung der DB liese sich in 1-2 Tagen komplett realisieren
Lonesome Walker
Hallo,
ich möchte ja jetzt nicht als Miesepeter dastehen. Aber ich würde empfehlen, das Problem durch Verzicht auf das Glossar zu lösen.
Brauchen wir hier wirklich einen Link, der uns erklärt, was ein "Server" oder eine "Firewall" ist? Und wenn es um "schwierigere" Begriffe geht ist ein Glossar m.E. nach sowieso schnell am Ende. Solche Begriffe bedürfen dann auch meist keiner allgemeinen Erklärung sondern sind oft Kontextabhängig (oder halt sehr umständlich zu erklären).
Vorschlag für eine Alternative: eine Funktion, mit der man ein Wort markieren und dann mit einem Mausklick in einer gängigen Suchmaschine suchen kann.
Gruß
Filipp
ich möchte ja jetzt nicht als Miesepeter dastehen. Aber ich würde empfehlen, das Problem durch Verzicht auf das Glossar zu lösen.
Brauchen wir hier wirklich einen Link, der uns erklärt, was ein "Server" oder eine "Firewall" ist? Und wenn es um "schwierigere" Begriffe geht ist ein Glossar m.E. nach sowieso schnell am Ende. Solche Begriffe bedürfen dann auch meist keiner allgemeinen Erklärung sondern sind oft Kontextabhängig (oder halt sehr umständlich zu erklären).
Vorschlag für eine Alternative: eine Funktion, mit der man ein Wort markieren und dann mit einem Mausklick in einer gängigen Suchmaschine suchen kann.
Gruß
Filipp
@scholl
Hi,
ich habe hier einen Codeschnipsel zu preg_replace_callback, der aus einer
Adresse in einem Text einen Link erstellt.
Analog dazu müsste es ja dann auch möglich sein, aus einem Link wieder eine Adresse zu machen, in dem man die entsprechenden Tags wieder entfernt.
Den Original-Schnipsel von Slava findest du hier http://www.bituniverse.com/forum/s/viewtopic.php/t,216/postdays,0/posto ...
Gruß
Günni
Hi,
ich habe hier einen Codeschnipsel zu preg_replace_callback, der aus einer
Adresse in einem Text einen Link erstellt.
Analog dazu müsste es ja dann auch möglich sein, aus einem Link wieder eine Adresse zu machen, in dem man die entsprechenden Tags wieder entfernt.
<?
$content = "Hier werden sie geholfen https://administrator.de, auf jeden Fall";
// Die Callback-Funktion
function repl($erg){
return $erg[1].'<a href="'.($erg[2]=='www.'?'http://'.$erg[2]:$erg[2]).$erg[3].'"
target="_blank">'.$erg[2].$erg[3].'</a>';
}
function mreplace($string){
$pattern = '#(^|\s)(https*://|ftp://|mailto:|news:|www\.)([^\s<>]+)#sm';
return preg_replace_callback($pattern,'repl',$string);
}
echo $content."<hr>";
echo mreplace($content);
?>
Den Original-Schnipsel von Slava findest du hier http://www.bituniverse.com/forum/s/viewtopic.php/t,216/postdays,0/posto ...
Gruß
Günni