0

私はhtmlのソースとキーワードの配列を持っています。キーワード配列内の任意のキーワードで始まるすべての単語を検索し、リンク タグでラップしようとしています。

たとえば、キーワード array には次の 2 つの値があります[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

subject 内の search のすべての出現箇所が指定された置換値に置き換えられた文字列または配列。

一致している文字列だけが置き換えられるわけではありません。あなたの例を使用して、この関数をデータセットに対して実行すると、各出現をABC複数のタグでラップすることになります(コードを実行して表示するだけですが、構文エラーを修正する必要があります)。

UTF-8 アルファベットで動作しますか?

確かではありませんが、書かれているように、そうではないと思います。Preg_Replace および UTF8を参照してください。PREG 関数はマルチバイトセーフである必要があります。

検索操作で各タグ内のすべての単語を無視したい

それは大変ですね。を回避する必要があります。<a ...>word</a>これにより、大きな混乱が早くなります。HTML を確実に一致させる正規表現は、ばかげた用事です。

おそらく最善の方法は、Web ページを XML または HTML として解釈することです。JavaScriptでこれを行うことを検討しましたか? なぜサーバー側で行うのですか?JS の利点は 2 つあります。1 つはクライアント側で実行されるため、作業をオフロード/分散できます。もう 1 つは、DOM が既に解釈されているため、すべてのテキスト ノードを見つけてかなり簡単に置き換えることができます。実際、私は、あなたが説明しているものとほぼ同じように、クロム拡張に取り組んでいる友人を助けていました。探していることを簡単に実行できるように変更できます。

より良い代替方法は?

絶対。ここで示しているのは、これを行う最悪の方法の 1 つです。私はあなたが使用することをお勧めします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 に答える