Поиск -> Выбор из текста фрагментов, содержащих найденные слова.

ASander

Новичок
Поиск -> Выбор из текста фрагментов, содержащих найденные слова.

Проблема в следующем:
Есть слова (поисковый запрос), есть текст содержащий эти слова.
По какому принципу (алгоритму) выбрать цитаты из текста, чтобы они максимально точно соответствовали запросу?
Например:
1 слово: просто выбираем любой фрагмент, в котором присутствует это слово,
2 слова: выбираем фрагмент, где эти слова наиболее близко друг к другу расположены (или если они далеко друг от друга – 2 фрагмента, каждый из которых содержит одно из слов);
а как быть с тремя и более словами?
Буду рад любой помощи (идее, алгоритму, готовому решению).
 

WP

^_^
PHP:
$t = 'Проблема в следующем:
Есть слова (поисковый запрос), есть текст содержащий эти слова.
По какому принципу (алгоритму) выбрать цитаты из текста, чтобы они максимально точно соответствовали запросу?
Например:
1 слово: просто выбираем любой фрагмент, в котором присутствует это слово,
2 слова: выбираем фрагмент, где эти слова наиболее близко друг к другу расположены (или если они далеко друг от друга – 2 фрагмента, каждый из которых содержит одно из слов);
а как быть с тремя и более словами? тест фрагмент слово тест
Буду рад любой помощи (идее, алгоритму, готовому решению). ';
$q = 'слов фрагмент';
preg_match_all('~\S+~',$q,$m);
$words = $m[0];
// тут по сути надо извлекать корень из всех слов, сам сделаешь через стеммер Портера который есть на dklab.ru
$expr = '';
for ($i = 0, $s = sizeof($words); $i < $s; ++$i)
{
 $expr .= preg_quote($words[$i],'~').($i+1 < $s?'|':'');
}
//setlocale(LC_ALL,'ru_RU.UTF-8');
preg_match_all('~(?:\W.{0,50}?\W)?\w*(?:\s*(?:'.$expr.')\s*)+\w*(?:\W.{0,50}?\W)?~',$t,$m);
$fragments = array();
for ($i = 0, $s = sizeof($m[0]); $i < $s; ++$i)
{
 $f = preg_replace('~^[\,\.\!\(\);\s]+|[\,\.\!\(\);\s]+$~','',$m[0][$i]);
 $fragments[] = $f;
}
// далее если надо поискать где ближе всего
$min_l = $max_c = $min_id =-1;
for ($i = 0, $s = sizeof($fragments); $i < $s; ++$i)
{
 preg_match_all('~'.$expr.'~',$fragments[$i],$m);
 for ($j = 0, $g = sizeof($m[0]); $j < $g; ++$j) {$m[0][$j] = strtolower($m[0][$j]);}
 $n = sizeof(array_unique($m[0]));
 if ($n <= $max_c) {continue;}

 if (!preg_match('~(?:'.$expr.').*(?:'.$expr.')~',$fragments[$i],$h))
 {
  if ($min_id == -1) {$min_id = $i; $min_c = $n;}
  continue;
 }
 $w = $h[0];
 $v = strlen(preg_replace('~'.$expr.'~','',$w));
 if ($v >= $min_l and $min_l != -1) {continue;}
 $min_id = $i;
 $min_c = $n;
 $min_l = $v;
}
var_dump($fragments[$min_id],$fragments); 
/*
string(24) "тест фрагмент слово тест"
array(12) {
  [0]=>
  string(24) "в следующем:
Есть слова"
  [1]=>
  string(40) "запрос), есть текст содержащий эти слова"
  [2]=>
  string(19) "Например:
1 слово:"
  [3]=>
  string(23) "выбираем любой фрагмент"
  [4]=>
  string(30) "котором присутствует это слово"
  [5]=>
  string(8) "2 слова:"
  [6]=>
  string(17) "выбираем фрагмент"
  [7]=>
  string(18) "эти слова наиболее"
  [8]=>
  string(60) "расположены (или если они далеко друг от друга – 2 фрагмента"
  [9]=>
  string(32) "из которых содержит одно из слов"
  [10]=>
  string(35) "а как быть с тремя и более словами?"
  [11]=>
  string(24) "тест фрагмент слово тест"
}
*/
 

ASander

Новичок
2 WP:
Спасибо, но все не так просто!
Судя по строчке
PHP:
!preg_match('~(?:'.$expr.').*(?:'.$expr.')~',$fragments[$i],$h)
, это код расчитан на запрос из 2х слов, это легко исправить, но даже с 2мя словами скрипт работает не совсем верно. Если убрать кусок "тест фрагмент слово тест", то логично, имхо, было бы выбрать "2 слова: выбираем фрагмент". Этого не происходит, т.к. после отработки 1го рег. выражения это 2 разных фрагмента. По какому принципу ты в самом начале выбираешь фрагменты?

Интересно было бы почитать, как это делают крупные поисковики (яндекс, гугл, рамблер...).
 

WP

^_^
> это код расчитан на запрос из 2х слов
Да хоть 100.
 

ASander

Новичок
Автор оригинала: WP
> это код расчитан на запрос из 2х слов
Да хоть 100.
Да хоть 1000 ) Но в вышеописанном рег. выражении проверяется наличие во фрагменте текста только двух слов из запроса.
 

WP

^_^
Ты можешь изменять выражение выбирающее фрагменты.
 
Сверху