anufriy
Новичок
Поиск предложений с определёнными словами, Сниппет
Понимаю, что задача кажется простой, но я довольно долго не могу её решить с помощью регвыров.
Задача состоит в том, чтобы выводить результаты поиска как в яндексе, в виде обрывков предложений с подсвеченными искомыми словами.
Для этого:
Вот немного облегченый алгоритм:
В упор не пашет регулярное выражение (это самое главное)
А весь код я привёл для того чтобы узнать мнение гуру, как в данном случае уменьшить ресурсоёмкость.
Я попытался поискать аналоги в нете и на форуме, но не нашёл. Понял только что это называется "Сниппет".
PS Сорри за длинный текст в примере - это чтоб тем кто историю не знает не было обидно и они могли узнать чем закончилось.
Понимаю, что задача кажется простой, но я довольно долго не могу её решить с помощью регвыров.
Задача состоит в том, чтобы выводить результаты поиска как в яндексе, в виде обрывков предложений с подсвеченными искомыми словами.
Для этого:
Передаю набор словоформ.
Передаю текст в котором искать
Регвыром ищу предложения с вхождениями
Сортирую по колличеству вхождений
Режу до приемлимой длинны учитывая, чтоб не вырезать вхождения.
Собираю несколько лучших предложений в результат. Короче аля Яндегз.
Вот немного облегченый алгоритм:
PHP:
$text = 'Реально зарегистрированный разговор между испанцами и американцами на частоте
"Экстремальные ситуации в море" навигационного канала 106 в проливе Финистерра
(Галиция) 16/10/97.
Испанцы: (помехи на заднем фоне) ... говорит А-853, пожалуйста, поверните на 15 градусов
на юг, во избежание столкновения с нами. Вы движетесь прямо на нас, расстояние 25 морских миль.
Американцы: (помехи на заднем фоне)... советуем вам повернуть на 15 градусов на север,
чтобы избежать столкновения с нами.
Испанцы: Ответ отрицательный. Повторяем, поверните на 15 градусов на юг во избежание
столкновения.
Американцы (другой голос): С вами говорит капитан корабля Соединенных Штатов Америки.
Поверните на 15 градусов на север во избежание столкновения.
Испанцы: Мы не считаем ваше предложение ни возможным, ни адекватным, советуем вам повернуть
на 15 градусов на юг, чтобы не врезаться в нас.
Американцы (на повышенных тонах): С ВАМИ ГОВОРИТ КАПИТАН РИЧАРД ДЖЕЙМС ХОВАРД, КОМАНДУЮЩИЙ
АВИАНОСЦА USS LINCOLN, ВОЕННО-МОРСКОГО ФЛОТА СОЕДИНЕННЫХ ШТАТОВ АМЕРИКИ, ВТОРОГО ПО ВЕЛИЧИТЕ
ВОЕННОГО КОРАБЛЯ АМЕРИКАНСКОГО ФЛОТА.
НАС СОПРОВОЖДАЮТ 2 КРЕЙСЕРА, 6 ИСТРЕБИТЕЛЕЙ, 4 ПОДВОДНЫЕ ЛОДКИ И МНОГОЧИСЛЕННЫЕ КОРАБЛИ ПОДДЕРЖКИ.
Я ВАМ НЕ "СОВЕТУЮ", Я "ПРИКАЗЫВАЮ" ИЗМЕНИТЬ ВАШ КУРС НА 15 ГРАДУСОВ НА СЕВЕР. В ПРОТИВНОМ
СЛУЧАЕ МЫ БУДЕМ ВЫНУЖДЕНЫ ПРИНЯТЬ НЕОБХОДИМЫЕ МЕРЫ ДЛЯ ОБЕСПЕЧЕНИЯ БЕЗОПАСНОСТИ НАШЕГО КОРАБЛЯ.
ПОЖАЛУЙСТА, НЕМЕДЛЕННО УБЕРИТЕСЬ С НАШЕГО КУРСА!!!!
Испанцы: С вами говорит Хуан Мануэль Салас Алкантара. Нас 2-е человек. Нас сопровождают пес,
ужин, 2 бутылки пива и канарейка, которая сейчас спит. Нас поддерживают радиостанция
"Cadena Dial de La Coruna" и канал 106 "Экстремальные ситуации в море". Мы не собираемся никуда
сворачивать, учитывая, что мы находимся на суше и являемся маяком А-853 пролива Финистерра
Галицийского побережья Испании. Мы не имеем ни малейшего понятия, какое место по величине мы
занимаем среди испанских маяков. Можете принять все е...ные меры, какие вы считаете необходимыми
и сделать все что угодно для обеспечения безопасности вашего е...го корабля, который разобьется
вдребезги об скалы. Поэтому еще раз настоятельно рекомендуем вам сделать наиболее осмысленную
вещь: изменить ваш курс на 15 градусов на юг во избежания столкновения.
Американцы: Ok, принято, спасибо.';
$words = array('градусов', 'корабля', 'избежание'); //Искомые слова и словоформы
$length = 200; //Максимальная длинна предложения в выводе
//убираем тэги
$text = preg_replace('@<script[^>]*?>.*?</script>@si',' ',$text);
$text = preg_replace('@<style[^>]*?>.*?</style>@si',' ',$text);
$text = preg_replace('@<[\/\!]*?[^<>]*?>@si',' ',$text);
//убираем двойные пробелы
$text = preg_replace('/\s+/', ' ', '.'.$text);
$text = str_replace(array('!', '?'), '.', $text);
preg_match_all('/\.[^\.]*(?:(?:('.implode(')|(',$words).')).*)+[^\.]*\./iU', $text, $matches, PREG_SET_ORDER);
//Создаём массив с весом слова в предложении
$count = array();
foreach($matches as $k => $v)
{
$d = $v[0];
unset($v[0]);
$v = array_flip($v);
unset($v[NULL]);
if(!is_numeric($count[$k])) $count[$k] = 0;
$count[$k]+=count($v);
}
//Сортируем по колличеству вхождений
arsort($count);
//Долго и нудно уменьшаем предложения в размере
$i = 0;
$text = '';
foreach($count as $k => $weight)
{
$text .= "<hr/>";
if(++$i > 2) break;
$t = $matches[$k][0];
$last = 0;
$last_len = 0;
foreach($words as $word)
{
$v = strrpos($t, $word);
if($v > $last)
{
$last = $v;
$last_len = strlen($word);
}
}
if($last < $length + 10)
{
$text .= substr($t,0,$length);
continue;
}
$first = strlen($t);
foreach($words as $word)
{
$v = strpos($t, $word);
if(is_numeric($v) && $first > $v)
$first = $v;
}
if($last - $first < $length)
{
$text .= '...'.substr($t,$last - $length + $last_len, $length);
continue;
}
$text .= substr($t,$first,$length);
$text .= $t;
}
//Ожирняем искомые слова
foreach($words as $word)
{
$text = str_replace($word,'<b>'.$word.'</b>',$text);
}
echo $text;
А весь код я привёл для того чтобы узнать мнение гуру, как в данном случае уменьшить ресурсоёмкость.
Я попытался поискать аналоги в нете и на форуме, но не нашёл. Понял только что это называется "Сниппет".
PS Сорри за длинный текст в примере - это чтоб тем кто историю не знает не было обидно и они могли узнать чем закончилось.
