在我的網站上我有天主教百科全書。它有超過11000篇文章。用鏈接替換單詞
我有興趣用我的網站上的文章替換單詞和短語,並鏈接到天主教百科全書中的相關條目。所以,如果有人說:
聖彼得是第一位教皇。
它應該用聖伯多祿文章的鏈接取代聖伯多祿,教皇與教皇文章的鏈接。
我有它的工作,但它非常緩慢。有超過30,000個可能的替代品,所以優化是非常重要的。我只是不確定該從哪裏出發。
這是我現有的代碼。請注意,它使用Drupal。而且,它會用[cathenlink]標籤替換單詞,並且該代碼稍後會在代碼中由真正的HTML鏈接替換。
function ce_execute_filter($text)
{
// If text is empty, return as-is
if (!$text) {
return $text;
}
// Split by paragraph
$lines = preg_split('/\n+/', $text, -1, PREG_SPLIT_DELIM_CAPTURE);
// Contains the parsed and linked text
$linked_text = '';
foreach ($lines as $line)
{
// If this fragment is only one or more newline characters,
// Add it to $linked_text and continue without parsing
if (preg_match('/^\n+$/', $line)) {
$linked_text .= $line;
continue;
}
// Select any terms that might be in this line
// Ordered by descending length of term,
// so that the longest terms get replaced first
$result = db_query('SELECT title, term FROM {catholic_encyclopedia_terms} ' .
"WHERE :text LIKE CONCAT('%', CONCAT(term, '%')) " .
'GROUP BY term ' .
'ORDER BY char_length(term) DESC',
array(
':text' => $line
))
->fetchAll();
// Array with lowercase term as key, title of entry as value
$terms = array();
// Array of the terms only in descending order of length
$ordered_terms = array();
foreach ($result as $r)
{
$terms[strtolower($r->term)] = $r->title;
$ordered_terms[] = preg_quote($r->term);
}
// If no terms were returned, add the line and continue without parsing.
if (empty($ordered_terms)) {
$linked_text .= $line;
continue;
}
// Do the replace
// Get the regexp by joining $ordered_terms with |
$line = preg_replace_callback('/\b('.
implode('|', $ordered_terms) .
')\b/i', function ($matches) use($terms)
{
if ($matches[1]) {
return "[cathenlink=" .
$terms[strtolower($matches[1])] . "]" .
$matches[1] . "[/cathenlink]";
}
},
$line);
$linked_text .= $line;
}
return $linked_text;
}
我正在做這樣的preg_replace,以便它不會替換一個單詞兩次。我會用strtr,但是沒有辦法確保它是一個完整的單詞,而不僅僅是一個單詞的一部分。
有什麼辦法可以讓這個更快嗎?現在它很慢。
謝謝。那麼,我必須使用像**或類似的東西來縮小結果,否則它會更慢,因爲它將返回所有30,000個以上的項。 – devbanana 2013-02-28 02:19:41
它應該是'%whatever%'?,你可以使用'%whatever'單獨優化它。 – 2013-02-28 02:22:43
是的,它必須是%term%,因爲否則該術語必須位於給定文本的開頭或結尾,因此不起作用。 – devbanana 2013-02-28 02:31:43