Помогите составить скрипт

Тема в разделе "PHP программирование", создана пользователем Vadik(R), 21 июн 2008.

  1. Vadik(R)

    Vadik(R) Well-Known Member

    Регистрация:
    12 дек 2007
    Сообщения:
    483
    Симпатии:
    0
    Люди, помогите, пожалуйста, написать скрипт.
    В общем хочу сделать поиск, чем-то похожий на поиск на некоторых форумах. Но проблема в том, что у меня просматриваются и html-теги. Объясню на примере.
    Пусть искомая строка <font color="#00ff00">fahrengeit</font>.
    Если пользователь захочет найти "fahrengeit", то результат будет выглядеть так
    <font color="#00ff00"><span color="yellow">fahrengeit</span></font>.
    Но если пользователь захочет найти "f", то у меня получится результат:
    <font color="#00<span color="yellow">f</span><span color="yellow">f</span>00"><span color="yellow">f</span>ahrengeit</font>.
    В том-то вся и проблема, как сделать замену подстрок, исключая абсолютно все теги (также надо исключать и все, что записано между тегами <script></script>).
    Жду помощи. Если есть специальная функция для решения моей задачи - буду рад.
     
  2. Vadik(R)

    Vadik(R) Well-Known Member

    Регистрация:
    12 дек 2007
    Сообщения:
    483
    Симпатии:
    0
    Люди, вот сегодня нашел более-менее подходящий код:
    Код (Text):
    function highlighter ($data) {
    $t=explode(' ', $_GET['text']);
    // получаем массив слов, которые нужно подсвечивать
    // Убираем из текста все теги в массив $tagList
    preg_match_all('#<[^>]*>#', $data, $tags); array_unique($tags);
    $tagList=array(); $k=0;
    foreach($tags[0] as $i) {
    $k++;
    $tagList[$k]=$i;
    $data=str_replace($i, '<' . $k . '>', $data);
    }
    // Производим обрамление текста <span>-ами
    foreach($t as $i)
    if (!is_numeric($i))
    $data=preg_replace('#' . $i . '#i', '<span class="highlight">$0</span>', $data);
    // Возвращаем все теги на место
    foreach($tagList as $k=>$i) $data=str_replace('<' . $k . '>', $i, $data);
    // Убираем все подсветки внутри тегов <title> ... </title>
    $data=preg_replace_callback(        '#<title>(.*?)<\/title>#',
    create_function(
    '$m',
    'return preg_replace("#<span([^>]*)>#", "", str_replace("</span>", "", $m[0]));'
    ),
    $data   );
    return $data; // Возвращаем подсвеченный текст
    }
    Только у меня по нему два вопроса:
    1. Как сделать callback для тегов <script></script>, <style></style>. Просто не знаю куда это вписать вообще, так как функции в php еще не проходил, так что лучше доделайте этот код(как я предполагаю получится 8 строчек).
    2. Почему если я делаю поиск со скобками, то он не работает, или вообще ничего не делает.
    Подробнее. Вот закачал страничку. Пока поиск идет только в имени закачавшем игру. Почему, если я набираю Vadik - цветом выделяет, если Vadik(R - вообще не пишет, а если полностью
    Код (Text):
    Vadik(R)
    - пишет имя, но не выделяет.
    Заранее спасибо.
     
  3. Vadik(R)

    Vadik(R) Well-Known Member

    Регистрация:
    12 дек 2007
    Сообщения:
    483
    Симпатии:
    0
    Вот еще нашел баг, если искать угловую скобку, то появляются откуда-то <1>,<2>,<3>,<4>...
    И для чего нужна вот эта вещь в алгоритме "if (!is_numeric($i))"?
     
  4. etc

    etc Гость

    Видать не помогут вам, ушли с пхп все :(
    Проверяют, мол а не нумерик ли $i.
     
  5. Vadik(R)

    Vadik(R) Well-Known Member

    Регистрация:
    12 дек 2007
    Сообщения:
    483
    Симпатии:
    0
    Ну да, а на чем же тогда форум написан?
     
  6. Flying

    Flying Гость

    как-то странно у вас всё происходит, обычно текст храниться отдельно от хтмл-кода страницы и поиск выполняется только по тексту...

    предложу варианты:
    1) использовать поиск, как на php.su (если ваш сайт хорошо индексируется яндексом)
    нагрузку с себя снимете (+)
    правда юзверя придется передавать яндексу (-)
    2) извращенно, но больше ничего не придумалось: убирать из кода теги, хранить оставшийся текст фрагментами (фрагмент текста - участок между тегами), для каждого фрагмента производить подсветку, а потом в первоначальном коде для каждого первичного фрагмента текста стр_реплейс на фрагмент с подсветкой
     
  7. Vadik(R)

    Vadik(R) Well-Known Member

    Регистрация:
    12 дек 2007
    Сообщения:
    483
    Симпатии:
    0
    Да, ладно, я уже эту тему забросил, решил, что овчинка выделки не стоит или я слишком маловат для этого.
     
  8. ARseny

    ARseny Гость

    для очистки тегов функция есть такая, strip_tags();
     
  9. Vadik(R)

    Vadik(R) Well-Known Member

    Регистрация:
    12 дек 2007
    Сообщения:
    483
    Симпатии:
    0
    Мда... Если б в этом проблема заключалась, я б не спрашивал на форуме. Как их потом обратно вставить? + Читай пост 2.
    Flying Если честно то для того сайта, где я хотел такое сделать - это не подойдет. А так на будущее второй вариант хоть и через ж..., зато смогу сам написать.
     
  10. GOsha

    GOsha Гость

    Да ну вас нафиг. Выгрузить код в strip_tags:

    strip_tags
    (PHP 3>= 3.0.8, PHP 4>)
    strip_tags - вырезает тэги HTML и PHP из строки.

    Описание
    string strip_tags (string str [, string allowable_tags])

    Эта функция пытается вернуть строку str с вырезанными тэгами HTML и PHP. Выдаёт ошибку с предупреждением в случае наличия неполных или ложных тэгов. Использует ту же машину вырезания тэгов, что и fgetss().

    Вы можете использовать необязательный второй параметр для специфицирования тэгов, которые не должны вырезаться.
    Примечание: allowable_tags был введён в PHP 3.0.13 и в PHP 4.0b3.

    Код (Text):
    Пример 1. strip_tags()
    $string = "<font .... ><b>Text</b></font>";
    $string = strip_tags($string, '<a><b><i><u>');
    //Вернет "<b>Text</b>"
    Ну и т.д. Т.е. Берешь страницы - гасишь теги. Находишь слова... Все просто.
     
  11. Vadik(R)

    Vadik(R) Well-Known Member

    Регистрация:
    12 дек 2007
    Сообщения:
    483
    Симпатии:
    0
    Так я же хочу хайлайт сделать. Я вырежу теги, найду слова, подсвечу его, а потом назад надо прежние теги вернуть. Только, честно говоря, я эту тему подзабросил, потому как для выполнения моей задачи мне кажется надо как-то по-другому сохранять данные на сервере. Либо вырезать теги самому, тогда, у меня есть идея, она немного через ж, зато будет работать :)
     
  12. GOsha

    GOsha Гость

    1. ВО! Ты сохрани куда-нить исходную строку.
    2. Найди в очищенной от тегов строке слова. И спиши их в массив.
    3. В исходной строке уже хайлайть найденные слова... ))))
    ПОнял?
     
  13. Vadik(R)

    Vadik(R) Well-Known Member

    Регистрация:
    12 дек 2007
    Сообщения:
    483
    Симпатии:
    0
    Здесь нельзя немного поподробнее?
    Пусть исходная строка $str="<font color='red'>red</font><font color='green'>green</font><font color='blue'>blue</font>";
    $s=$str; // Сохраняем исходную строку
    strip_tags($str); // Вырезали теги
    $findstr="green";
    Дальше немного поподробнее хотел бы, но в результате должно получится:
    $str="<font color='red'>red</font><font color='green'><span class='hl'>green</span></font><font color='blue'>blue</font>";
    Если знаешь, то пожалуйста напечатай! Потому как я не знаю, как далее реализовать твой алгоритм.
     
  14. GOsha

    GOsha Гость

    С помощюь preg_match_all собираем все в массив, который содержит ваш текст разбитый на теги:
    Подсказка:
    Код (Text):
    preg_match_all("/тут регулярное выражение/",$str,$matcharr,PREG_SET_ORDER);
    Получим массив:
    Код (Text):
    $matcharr[0] = "<font color='red'>";
    $matcharr[1] = "red";
    $matcharr[2] = "</font>";
    ...
    Далее проходим по массиву array_walk(). выбираем и заменяем текст в строках, который не начинается с "<";

    *Возможно это не самый короткий, но все же путь.

    Не забудьте собрать массив обратно в строку. implode()
     
  15. Vadik(R)

    Vadik(R) Well-Known Member

    Регистрация:
    12 дек 2007
    Сообщения:
    483
    Симпатии:
    0
    У меня прогресс очень хороший. Правда решил доделать код в 2 посте. Вот, что получил:
    Код (Text):
    <?php
    setlocale(LC_ALL, array ('ru_RU.CP1251', 'rus_RUS.1251'));
    /*
    Ограничения поиска:
    Для работы с тегами <title>, <style>, <script> и т. п. где между ними размещен "особый" код, надо создавать
    свой список таких тегов.
    Callback не будет работать правильно, если теги будут повторятся. То есть для следующей строки поиск не сработает:
    "<script></script>какой-то текст<script></script>".
    Алгоритм никогда не сможет найти слово Вадим в строке "<font size='7'>В</font>адим".
    Такой поиск сделать можно, но его надо очччень хорошо продумать и алгоритм там будет другой. Придется писать
    свою функцию replace_str, так, что бы она при проходе от первого сивола к последнему считала строки
    "<$i>" как за пустые ("").
    */
    function highlighter ($data, $mystr) {
    // Массив тегов (определены, как регулярные выражения)
    $specialTags=array("<title>", "<\/title>", "<style>", "<\/style>", "<script([^>]*)>", "<\/script>");
    // Открывающая строка для подсветки
    $firststr='<span style="color:#ff0000;">';
    // Закрывающая строка для подсветки
    $secondstr='</span>';
    // Получаем массив слов которые надо подсвечивать и заодно заменяем спец. символы html-сущностями.
    $t=explode(' ', html_entity_decode($mystr, ENT_QUOTES, "Windows-1251"));
    // Удаляем повторяющиеся слова. Ведь бывают же извращенцы;)
    $t=array_unique($t);
    // Выполняем процедуру подсветки для каждого слова
    foreach($t as $hren) {
    // Получаем список тегов
    preg_match_all('#<[^>]*>#', $data, $tags);
    // Удаляем повторяющиеся теги
    $tags=array_unique($tags);
    // Без комментариев;)
    $tagList=array(); $k=0;
    // $tags=Array of Array; Там находятся все теги, поэтому делаем двойной цикл.
    foreach($tags as $hren1) {
    foreach($hren1 as $i) {
    // Увеличиваем размер массив
    $k++;
    // Заносим в массив новый уникальный тег
    $tagList[$k]=$i;
    // А в строке заменяем этот тег на "<номер элемента массива, в котором мы сохранили тег>"
    $data=str_replace($i, '<'.$k.'>', $data);
    }
    }
    // Производим обрамление текста <span>-ами
    $data=str_replace($hren, $firststr.$hren.$secondstr, $data);
    // Если пользователь ищет цифры, то они могут встретится в тегах. Поэтому возвращаем замененные теги назад
    $data=str_replace('<'.$firststr.$hren.$secondstr.'>', '<'.$hren.'>', $data);
    // Убираем все подсветки внутри "особых" тегов
    /*for($i=0; $i<=(length($specialTags)+1)/2; $i++) {
    for ($j=1; $j<=$k; $j++) {
    if ($s)
    $data=preg_replace_callback(        '#'.tag1.'(.*?)'.tag2.'#',
    create_function(
    '$m',
    'return str_replace("<".$firststr.$hren.$secondstr.">", "<".$hren.">", $data);'
    ),
    $data   );
    }
    }*/
    // Возвращаем все теги на место
    foreach($tagList as $k=>$i) $data=str_replace('<'.$k.'>', $i, $data);
    }
    return $data; // Возвращаем подсвеченный текст
    }
    echo highlighter("Vadik(R)", "(R)");
    ?>
    Единственное, осталось проверить правильно ли я сделал регулярные выражения и дописать функцию preg_replace_callback. Сам не ожидал от себя такого результата :)
     
  16. GOsha

    GOsha Гость

    Окак... )) Вперед... Как говорил мой дедушка-ветеран "Сиськи на амбразуры!" )))
    А проверить вы и сами сможете...

    Маньяк)
     
  17. Vadik(R)

    Vadik(R) Well-Known Member

    Регистрация:
    12 дек 2007
    Сообщения:
    483
    Симпатии:
    0
    Почти доделал. Только callback не работает. А как сделаю, так опубликую, может кому пригодится :)
    Сам долго искал в нете, нашел и то пришлось дорабатывать.

    Ну вот, вроде и все. Вот окончательный код:
    Код (Text):
    <?php
    setlocale(LC_ALL, array ('ru_RU.CP1251', 'rus_RUS.1251'));
    /*
    Ограничения поиска:
    Работает только с учетом регистра.
    Для работы с тегами <title>, <style>, <script> и т. п. где между ними размещен "особый" код, надо создавать
    свой список таких тегов.
    Callback не будет работать правильно, если одинаковые специальные теги будут вложены. То есть для следующей
    строки подсветка сработает неправильно: "<script><script></script></script>".
    Алгоритм никогда не сможет найти слово Вадим в строке "<font size='7'>В</font>адим".
    Такой поиск сделать можно, но его надо очччень хорошо продумать и алгоритм там будет другой. Придется писать
    свою функцию replace_str, так, что бы она при проходе от первого сивола к последнему считала строки
    "<$i>" как за пустые ("").
    */
    function myfunc($x) {
    $firststr='<span style="color:#ff0000;">';
    $secondstr='</span>';
    return str_replace($firststr, "", str_replace($secondstr, "", $x));
    }
    function highlighter ($data, $mystr) {
    // Массив тегов (определены, как регулярные выражения)
    $specialTags=array("<title>", "<\/title>", "<style>", "<\/style>", "<script[^>]*?>", "<\/script>");
    // Открывающая строка для подсветки
    $firststr='<span style="color:#ff0000;">';
    // Закрывающая строка для подсветки
    $secondstr='</span>';
    // Получаем массив слов которые надо подсвечивать и заодно заменяем спец. символы html-сущностями.
    $t=explode(' ', htmlspecialchars($mystr, ENT_QUOTES, "Windows-1251"));
    // Удаляем повторяющиеся слова. Ведь бывают же извращенцы;)
    $t=array_unique($t);
    // Выполняем процедуру подсветки для каждого слова
    foreach($t as $hren) {
    // Получаем список тегов
    preg_match_all('#<[^>]*?>#', $data, $tags);
    // Без комментариев;)
    $tagList=array(); $k=0;
    // В $tags[0] полное совпадение по шаблону, там находятся все теги
    foreach($tags[0] as $i) {
    // Увеличиваем размер массив
    $k++;
    // Заносим в массив новый уникальный тег
    $tagList[$k]=$i;
    // А в строке заменяем этот тег на "<номер элемента массива, в котором мы сохранили тег>"
    $data=substr_replace($data, '<<'.$k.'>>', strpos($data, $i), strlen($i));
    }
    // Производим обрамление текста <span>-ами
    $data=str_replace($hren, $firststr.$hren.$secondstr, $data);
    // Если пользователь ищет цифры, то они могут встретится в тегах. Поэтому возвращаем замененные теги назад
    $data=preg_replace_callback(        '#<(([0-9])*?(<[^>]*?>)*?)*?>#',
    create_function(
    '$m',
    'return myfunc($m[0]);'
    ),
    $data   );
    // Убираем все подсветки внутри "особых" тегов
    $ffirst=0;
    $ssecond=0;
    for($i=0; $i<=(count($specialTags)-1)/2; $i++) {
    for ($j=1; $j<=$k; $j++) {
    if (preg_match ("/".$specialTags[$i*2]."/i", $tagList[$j])) $ffirst="<<".$j.">>";
    if (preg_match ("/".$specialTags[$i*2+1]."/i", $tagList[$j])) $ssecond="<<".$j.">>";
    if ($ffirst && $ssecond) {
    $data=preg_replace_callback(        '#'.$ffirst.'(.*?)'.$ssecond.'#',
    create_function(
    '$m',
    'return myfunc($m[0]);'
    ),
    $data   );
    $ffirst=0;
    $ssecond=0;
    }
    }
    }
    // Возвращаем все теги на место
    foreach($tagList as $k=>$i) $data=str_replace('<<'.$k.'>>', $i, $data);
    }
    // Возвращаем подсвеченный текст
    return $data;
    }
    ?>
    Хотелось бы, что бы вы его потестили, а то может чего я из виду и упустил. Но проверял несколько раз. Все равно не верится, что у меня получилось. Думал лет в 20 такое напишу, когда будет работа и т. д. и т. п.
    А так всем спасибо за участие и поддержку. Сейчас все будут награждены плюсиками :)
     
Загрузка...
Похожие Темы - Помогите составить скрипт
  1. limbra
    Ответов:
    3
    Просмотров:
    44
  2. NylevoiChelovek
    Ответов:
    4
    Просмотров:
    99
  3. Ruska132
    Ответов:
    34
    Просмотров:
    269
  4. gURaBA_N
    Ответов:
    7
    Просмотров:
    147
  5. uxbmw3w
    Ответов:
    0
    Просмотров:
    62

Поделиться этой страницей