0

我有一个 html 源和一组关键字。我正在尝试查找以关键字数组中的任何关键字开头的所有单词并将其包装在链接标记中。

例如,关键字数组有两个值:[ABC, DEF]. 它应该匹配ABCDEF,DEFAD等,并用超链接标记包装每个单词。

这是我到目前为止的代码:

$_keys = array('ABC', 'DEF');
$text = 'Some ABCDD <strong>HTML</strong> text. DEF';

function search_and_replace(($key,$text)
{
    $words = preg_split('/\s+/', trim($text)); //to seprate words in $_text
    for($words as $word) 
    {
        if(strpos($word,$key) !== false)
        {
            if($word.startswith($key)) 
            {
                str_replace($word,'<a href="">'.$word.'</a>,$_text);
            }
        }

    }
    return text;
}


for($_keys as $_key)
{
    $text = search_and_replace($key,$text);
}

我的问题:

  1. 这个算法会起作用吗?
  2. 我将如何修改它以使用 UTF-8?
  3. 如何识别 html 中的超链接并忽略它们(不想在超链接中放置超链接)。
  4. 这个算法安全吗?
4

4 回答 4

2

算法是“真的”吗?(我正在阅读“准确”)

不它不是。由于str_replace 功能如下

用给定的替换值替换主题中所有出现的搜索的字符串或数组。

您匹配的字符串不是唯一被替换的字符串。使用你的例子,如果你对你的数据集运行这个函数,你最终会ABC在多个标签中包装每个出现的 (只需运行你的代码来查看它,但你必须修复语法错误)。

使用 UTF-8 字母

不确定,但正如所写,我不这么认为。请参阅Preg_Replace 和 UTF8。PREG 函数应该是多字节安全的。

我想在每个标签中查找所有单词以进行搜索操作

这太难了。你必须避免<a ...>word</a>,这开始迅速搞得一团糟。可靠地匹配 HTML 的正则表达式是徒劳的。

最好的办法可能是将网页解释为 XML 或 HTML。您是否考虑过在 javascript 中执行此操作?为什么要在服务器端呢?JS 的优点是双重的 - 第一,它在客户端运行,因此您正在卸载/分发工作,第二,由于 DOM 已经被解释,您可以找到所有文本节点并相当容易地替换它们。事实上,我正在帮助一个正在开发chrome 扩展的朋友,几乎完全符合您的描述;您可以修改它以轻松完成您正在寻找的事情。

更好的替代方法?

确实。你在这里展示的是一种更糟糕的方法。我会推动您使用preg_replace(另一个答案对于您想要的正则表达式有一个良好的开端,匹配的断词比空格更合适)但是由于您想避免更改某些元素,所以我现在正在考虑在 JS 中执行此操作客户端要好得多。

于 2014-03-23T16:58:28.820 回答
1

为了最大化您的性能,您应该查看Trie(相同Retrieval Tree)数据结构。( http://en.wikipedia.org/wiki/Trie ) 如果我是你,我会首先构建一个Trie包含 HTML 页面中的单词。在此步骤中,您还可以检查单词是否在<a>标签内,如果是,则不要将其添加到Trie. Regex您可以通过比赛轻松做到这一点

于 2014-03-23T16:47:37.057 回答
1

正则表达式怎么样?

preg_match_all("/\b".$word."\B*\b/",$matches);
foreach($matches as $each) {
    print($each[0]);
}

(对不起,我的 PHP 有点生疏了)

于 2014-03-23T16:49:21.207 回答
1

对于像这样的简单任务,PHP 正则表达式会很好用。这个想法是找到所有超链接(以及可选的一些其他 HTML 元素)并用唯一的标记替换它们。之后,我们可以自由地寻找和替换所需的关键字,最后我们会将删除的 HTML 元素恢复回来。

$_keys = array( 'ABC', 'DEF', 'ABČ' );

$text = 
'Some <a href="#" >ABC</a> ABCDđD <strong>ABCDEF</strong> text. DEF
<p class="test">
    <a href="#">PHP</a> is <em>the</em> most ABCwidely used 
    langČuage ABC for ABČogr ammDEFing on the webABC DEFABC.
</p>';

// array for holding html items replaced with tokens
$tokens = array();
$id = 0;

// we will replace all links and strong elements (a|strong)
$text = preg_replace_callback( '/<(a|strong)[^>]*>.*?<\/\1\s*>/s', 
    function( $matches ) use ( &$tokens, &$id ) 
    {
        // store matches into the tokens array
        $tokens[ '#'.++$id.'#' ] = $matches[0];
        // replace matches with the unique id
        return '#'.$id.'#';
    }, 
    $text 
);

echo htmlentities( $text );
/* - outputs: Some #1# ABCDđD #2# text. DEF <p class="test"> #3# is <em>the</em> most ABCwidely used langČuage ABC for pćrogrABCamming on the webABC DEFABC. </p>
   - note the #1# #2# #3# tokens
*/

// wrap the words that starts with items in $_keys array ( with u(PCRE_UTF8) modifier )
$text = preg_replace( '/\b('. implode( '|', $_keys ) . ')\w*\b/u', '<a href="">$0</a>', $text );

// replace the tokens with values
$text = str_replace( array_keys($tokens), array_values($tokens), $text );       

echo $text;

PHP 正则表达式中有关 UTF-8 字符串的信息:

于 2014-03-23T19:30:35.003 回答