Подсветка результатов поиска на странице
Сложно представить современный web-сайт без поиска. И хорошим тоном считается не просто выводить все страницы, на которых был найден запрошенный результат, но и как-нибудь выделять искомые слова в тексте. Если контент сайта представляет собой обычный текст без html-разметки, то тут все просто, достаточно использовать что-то типа str_replace. А как быть, если на странице имеются html-теги, и надо выделить только тот текст, который не заключен внутри тегов? Например, нам надо выделить слово "поиск" в такой тестовой строке:Code (HTML) : Убрать нумерацию
- Для поиска и просмотра <a href="/search" title="Результаты поиска">результатов
- поиска</a> пройдите по поисковой ссылке.
Code (HTML) : Убрать нумерацию
- Для <b>поиск</b>а и просмотра <a href="/search" title="Результаты <b>поиск</b>а">
- результатов <b>поиск</b>а</a> пройдите по <b>поиск</b>овой ссылке.
Code (PHP) : Убрать нумерацию
- // Искомая строка для подсветки на странице
- $search = 'html';
- // Создаем строку для регулярного выражения
- $pattern = "/((?:^|>)[^<]*)(".$search.")/si";
- // Подсвеченная строка
- $replace = '$1<b style="color:#FF0000; background:#FFFF00;">$2</b>';
- // Заменяем
- $html = preg_replace($pattern, $replace, $html);
Протестируем скрипт. Для примера возьмем небольшую html-страницу с текстом и html-тегами и попробуем подсветить на ней все вхождения слова "html". Обратите внимание, что эта строка встречается не только в тексте, но и в самой разметке страницы, в адресе ссылки, а также в атрибуте title.
Code (HTML) : Убрать нумерацию
- <html>
- <head><title>Тестовая страница</title></head>
- <body>
- HTML (от англ. HyperText Markup Language — язык разметки гипертекста) -
- стандартный язык разметки документов во Всемирной паутине. Большинство
- веб-страниц создаются при помощи
- <a href="http://ru.wikipedia.org/wiki/HTML" title="Описание языка HTML">языка
- HTML</a> (или XHTML).
- </body>
- </html>
Результат подсветки
Теперь посмотрим на исходный код, не поломалось ли чего. Нет, и тут все в порядке. Подсвечен только текст вне тегов, внутри тегов он остался без изменения.
Исходный код подвеченной страницы
Если используется релевантный поиск, то регулярное выражение для подсветки можно доработать таким образом, чтобы подсвечивались несколько слов по отдельности и вся поисковая фраза целиком. Это вы можете сделать самостоятельно.
Просмотров: 12686 | Комментариев: 7
Метки: PHP, регулярные выражения
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
ManHunter
(20.03.2015 в 02:51):
$search = 'html';
function replace($string) {
global $search;
return preg_replace('/'.$search.'/is',
'<b style="color:#FF0000; background:#FFFF00;">\\0</b>', $string[1]);
}
$html=preg_replace_callback('/(?<=^|>)([^<>]+)(?=$|<)/s ', 'replace', $html);
в код сам вставишь.
function replace($string) {
global $search;
return preg_replace('/'.$search.'/is',
'<b style="color:#FF0000; background:#FFFF00;">\\0</b>', $string[1]);
}
$html=preg_replace_callback('/(?<=^|>)([^<>]+)(?=$|<)/s ', 'replace', $html);
в код сам вставишь.
Влад
(20.03.2015 в 01:08):
Все работает круто, спасибо, но вот что я нашел, и не смог изменить regexp самостоятельно:
когда текст, где надо делать замены, такой, например:
<span style="color: black;">This is for REPLACE</span>
При замене REPLACE - все ок
Но есть в строке несколько вхождений заменяемой фразы, то заменяется только ПОСЛЕДНЯЯ:
<span style="color: black;">REPLACE examle - this is for REPLACE</span>
в этом примере заменится только последний REPLACE, а первый останется незамеченным :((
В какую сторону regexp-правил можно смотреть, чтобы учесть ВСЕ вхождения??
Спасибо заранее за совет!
когда текст, где надо делать замены, такой, например:
<span style="color: black;">This is for REPLACE</span>
При замене REPLACE - все ок
Но есть в строке несколько вхождений заменяемой фразы, то заменяется только ПОСЛЕДНЯЯ:
<span style="color: black;">REPLACE examle - this is for REPLACE</span>
в этом примере заменится только последний REPLACE, а первый останется незамеченным :((
В какую сторону regexp-правил можно смотреть, чтобы учесть ВСЕ вхождения??
Спасибо заранее за совет!
JokerBaD
(16.02.2013 в 23:52):
Спасибо за пример.Все разжевано и понятно в копилку знаний может пригодится.Регулярные выражения мощная вещь.
ManHunter
(07.02.2013 в 16:59):
Я в статье это для красоты написал что ли? "Код также немного упрощен для удобства восприятия. В реальных проектах при составлении регулярного выражения $pattern надо обязательно экранировать в искомой строке все служебные символы, которые могут быть использованы в регулярных выражениях."
Тем более, что там уязвимость была, насколько я знаю, в параметре lastdate, а не в подсветке.
Тем более, что там уязвимость была, насколько я знаю, в параметре lastdate, а не в подсветке.
ЖУК
(07.02.2013 в 16:57):
был такой поиск у IPB до версии 2.1.5 включительно.
позволял выполнять произвольный php код при условии поиска по постам юзеров.
фильтруйте $search
позволял выполнять произвольный php код при условии поиска по постам юзеров.
фильтруйте $search
Толян
(07.02.2013 в 15:42):
Круть!
Добавить комментарий
Заполните форму для добавления комментария
Поделюсь, как видоизменил, чтобы можно было выделять несколько слов и выделялось css-классами:
$html_lit = '<html>Text of html page to replace with color lighting. Used html tags "span" and "class" defined.</html>';
$words_and_classes = array ();
$words_and_classes[] = array ( 'word' => 'html', 'class' => 'light_1');
$words_and_classes[] = array ( 'word' => 'with color', 'class' => 'light_2');
foreach ($words_and_classes as $one) {
$regs_search = '/'.preg_quote($one['word'], '/').'/usi';
$regs_replace = '<span class="'. $one['class'] .'">\\0</span>';
$html_lit = preg_replace_callback(
'/(?<=^|>)([^<>]+)(?=$|<)/usi',
function ($string) use ($regs_search, $regs_replace) {
return preg_replace(
$regs_search,
$regs_replace,
$string[1]);
},
$html_lit);
}
Отличная вещь - regexp!