0

在我的网站上,我有天主教百科全书。它有超过 11,000 篇文章。

我有兴趣将我网站上文章中的单词和短语替换为天主教百科全书中相关条目的链接。所以,如果有人说:

圣彼得是第一位教皇。

它应该用指向关于圣彼得的文章的链接替换圣彼得,用指向关于教皇的文章的链接替换教皇。

我有它的工作,但它很慢。有超过 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,但是没有办法确保它是一个完整的单词,而不仅仅是单词的一部分。

有什么办法可以让这更快吗?现在它很慢。

4

3 回答 3

0

好的,我认为我这样做的方式可能是最有效的。我想出的是将结果缓存一周,这样帖子就不必每周解析一次以上。实施此解决方案后,我发现网站的速度有了显着提高,因此它似乎可以正常工作。

于 2013-02-28T20:56:00.320 回答
0

您可以使用诸如 Lucene 之类的索引系统来索引天主教百科全书。我不怀疑它经常变化,因此可以每天更新索引。Lucene 是用 Java 编写的,但我知道 Zend 有一个可以读取索引的 PHP 模块。

于 2013-02-28T11:30:42.290 回答
0

我认为LIKE关键字会减慢您的速度。是indexed吗?

你可以在这里找到一些线索

于 2013-02-28T02:05:22.077 回答