Генерация ключевиков по содержимому. (snippet)

Сниппет генерации ключевых слов на основе указанных полей. Сниппет вычищает мусор и дубли слов, так же можно указать минимальное число символов (в слове) для вырезки.

Автор сниппета — liberpro . Сниппет имеет возможность обработки tv, но за донат :)

оригинал топика

[!keyw? &id=`2` &fields=`longtitle,alias` &min=`5` &limit=`10`!]




Установка: создаем новый сниппет, называем keyw, вставляем содержимое.

<?php
$id = isset($id) ? $id : $modx->documentIdentifier; // id документа откуда брать поля, по умолчанию текущий документ
$fields = isset($fields) ? $fields : 'pagetitle,content,introtext'; // основные поля документа
$min = isset($min) ? $min : 4; //минимальное количество символов в слове при выборке
$limit = isset($limit) ? $limit : 20; // сколько слов выводить


if (!$fields) return;
$f = array();
foreach(explode(',',$fields) as $field) $f[] = trim($field);
$fields_mysql = implode('`," ",`',$f);
$str = $modx->db->getValue('Select concat(`'.$fields_mysql.'`) from '.$modx->getFullTableName('site_content').' where `id`='.$id);

//Чистим, приводим к массиву
$str = strip_tags($str);
$str2 = preg_replace('/[^a-zA-Zа-яА-Я0-9\s]/ui', ' ',$str ); 
$str2 = str_replace('  ',' ',$str2);
$str2 = str_replace(PHP_EOL,' ',$str2);
$arr = explode(' ',$str2);
foreach($arr as $key=>$val) if ($val) $arr[$key] = mb_strtolower(trim($val),'utf-8');

//Выбираем наиболее часто встречающиеся
$array_words = array_count_values($arr);
arsort($array_words);
$out = array();
foreach($array_words as $word => $val)
{
if (mb_strlen($word,'utf-8')>=$min) $out[]=$word;
if (count($out)==$limit) break;
}
	
return implode(',',$out);
?>


и аналогичный скрипт, только в виде плагина:
$ttv = $modx->getFullTableName('site_tmplvar_contentvalues');
$tvid = 3; //id tv, куда пишем ключевики
$fields = isset($fields) ? $fields : 'pagetitle,content,introtext'; // основные поля документа
$min = isset($min) ? $min : 4; //минимальное количество символов в слове при выборке
$limit = isset($limit) ? $limit : 20; // сколько слов выводить


if (!$fields) return;
$f = array();
foreach(explode(',',$fields) as $field) $f[] = trim($field);
$fields_mysql = implode('`," ",`',$f);
$str = $modx->db->getValue('Select concat(`'.$fields_mysql.'`) from '.$modx->getFullTableName('site_content').' where `id`='.$id);

//Чистим, приводим к массиву
$str = strip_tags($str);
$str2 = preg_replace('/[^a-zA-Zа-яА-Я0-9\s]/ui', ' ',$str ); 
$str2 = str_replace('  ',' ',$str2);
$str2 = str_replace(PHP_EOL,' ',$str2);
$arr = explode(' ',$str2);
foreach($arr as $key=>$val) if ($val) $arr[$key] = mb_strtolower(trim($val),'utf-8');

//Выбираем наиболее часто встречающиеся
$array_words = array_count_values($arr);
arsort($array_words);
$out = array();
foreach($array_words as $word => $val)
{
if (mb_strlen($word,'utf-8')>=$min) $out[]=$word;
if (count($out)==$limit) break;
}
$tid = $modx->db->getValue('Select `id` from '.$ttv.' where contentid='.$id.' and tmplvarid='.$tvid);
if ($c==1) $modx->db->update(array('value'=>implode(',',$out)),$ttv ,'id='.$tid);
else $modx->db->insert(array('contentid'=>$id,'tmplvarid'=>$tvid,'value'=>implode(',',$out)),$ttv);


реквизиты для доната:

Банковские карты РФ
Bank Avangard, Visa — 4038 9682 7273 2633, Liber Alexey
SberBank, Visa — 4276 4000 7159 1094, Liber Alexey

Альтернативные способы:
Яндекс.Деньги — 410012714062964
Qiwi кошелек (в самом крайнем случае) — +7(967)044-03-33

29 комментариев

avatar
Интересно, но уже давно не работаю с эво.

Добавить tv для ресурса, в которое будет записываться значение ключей, для того чтобы при каждом открытии страницы не генерировать одно и тоже.
avatar
это будет не совсем правильно, контент меняется соответственно и могут меняться ключи, тогда надо будет думать о дате редактирования документа, или чекбокс на перегенерацию, так же я бы подумал о — например, кол-во знаков в слове, могут попадать предлоги и т.п. так же, список стоп слов то что не стоит включать в ключи, а на основании этого сниппета построить просто генерацию тегов для материала было бы интереснее думаю, а так попилить его и будет супер )
avatar
можно пилить и пилить, вот только бесплатно это никому не нужно) Если будет донат, я думаю автор допилит нужные в нём функции. Хотя как по мне, тот функционал который есть сейчас — решает задачу на 99%.
avatar
согласен, основное готово, если кому то надо будет или сам допилит или донат, я так думаю под всех в любом случае не угодишь
avatar
Мне сложно предсказать поведение поисковых систем, но, как мне кажется, если записать keywords="[*pagetitle*],[*keyw*],[!keyw!]" — вес страницы будет чуть больше, чем без онного сниппета. Понятное дело, что этот скрипт не даст ошеломляющих результатов, и не существует в природе палочки, которая вжух, и ты на первом месте в выдаче. Но там чуть-чуть, там чуть-чуть — так и набирается вес.
Плюс к этому, как предложил DiTso , можно использовать данный скрипт для тэгов.
А на счет скорости — право не знаю, что больше берет ресурсов: вызов сниппета или сама работа сниппета) А если убрать запрос, и напрямую обратиться к documentObject (но это будет работать только для текущего документа), то там ваще копейки будут.
Ну и самое главное — в modx не существует решений, который поставил и ты счастлив. Все приходится малость допиливать руками. Например тот же список стоп-слов есть в полной версии. Здесь же представлена болванка, которую можно крутить в разные стороны...
P.S. На счет доната — не моя затея)
avatar
нет смысла писать данные в tv, так как контент и вправду может меняться + размер базы вырастет в разы. Сниппет отдает очень быстро данные, поэтому решение годное)
Очень упрощает работу манагеру, который заполняет сайт.
avatar
Но кто мешает, например, при редактировании добавить плагин, который при редактировании удаляет данные из ТВ?

База, да пусть она разрастается, зато каждый раз при запросе страницы не будет генерироваться, по сути, не столь важный на данный момент параметр для поисковиков.
Комментарий отредактирован 2017-01-22 10:45:56 пользователем damapic
avatar
согласен, с плагином — здесь лучше решение, чем делать это через сниппет, особенно при такой реализации как предлагается в топике
avatar
Не совсем понял, чем не устраивает такая реализация? Предложите свой вариант…
avatar
столь — не столь, а когда идёт борьба за первое место — играет роль каждый параметр и картина по сайту в целом.
avatar
По просьбам трудящихся — тоже самое в виде плагина. Событие OnDocFormSave
$ttv = $modx->getFullTableName('site_tmplvar_contentvalues');
$tvid = 3; //id tv, куда пишем ключевики
$fields = isset($fields) ? $fields : 'pagetitle,content,introtext'; // основные поля документа
$min = isset($min) ? $min : 4; //минимальное количество символов в слове при выборке
$limit = isset($limit) ? $limit : 20; // сколько слов выводить


if (!$fields) return;
$f = array();
foreach(explode(',',$fields) as $field) $f[] = trim($field);
$fields_mysql = implode('`," ",`',$f);
$str = $modx->db->getValue('Select concat(`'.$fields_mysql.'`) from '.$modx->getFullTableName('site_content').' where `id`='.$id);

//Чистим, приводим к массиву
$str = strip_tags($str);
$str2 = preg_replace('/[^a-zA-Zа-яА-Я0-9\s]/ui', ' ',$str ); 
$str2 = str_replace('  ',' ',$str2);
$str2 = str_replace(PHP_EOL,' ',$str2);
$arr = explode(' ',$str2);
foreach($arr as $key=>$val) if ($val) $arr[$key] = mb_strtolower(trim($val),'utf-8');

//Выбираем наиболее часто встречающиеся
$array_words = array_count_values($arr);
arsort($array_words);
$out = array();
foreach($array_words as $word => $val)
{
if (mb_strlen($word,'utf-8')>=$min) $out[]=$word;
if (count($out)==$limit) break;
}
$tid = $modx->db->getValue('Select `id` from '.$ttv.' where contentid='.$id.' and tmplvarid='.$tvid);
if ($c==1) $modx->db->update(array('value'=>implode(',',$out)),$ttv ,'id='.$tid);
else $modx->db->insert(array('contentid'=>$id,'tmplvarid'=>$tvid,'value'=>implode(',',$out)),$ttv);
avatar
А что слова не так вот выдираете? ;)
$words=str_word_count($text, 1,"АаБбВвГгДдЕеЁёЖжЗзИиЙйКкЛлМмНнОоПпРрСсТтУуФфХхЦцЧчШшЩщЪъЫыЬьЭэЮюЯя");
print_r($words);
avatar
Можно проще и с ТВ, но без сортировки по частоте появления в тексте:
Сниппет getWords
Вызов: [!getWords? &text=`любой текст`!]
Пример: [!getWords? &text=`[*pagetitle*] [*content*] [*мояTV*]`!]
Код сниппета:

$minlen=2; //Минимальная длина слова
$nowords=explode(",","звать,приглашать,принять,участие"); //Слова для исключения
$words=str_word_count($text, 1,"АаБбВвГгДдЕеЁёЖжЗзИиЙйКкЛлМмНнОоПпРрСсТтУуФфХхЦцЧчШшЩщЪъЫыЬьЭэЮюЯя");
foreach ($words as &$word) {
 if (mb_strlen($word)>$minlen && !in_array($word,$nowords)){
	 $nm[]=mb_strtolower($word);
 }
}
$nm=array_unique($nm);
return @implode(",", $nm);
Комментарий отредактирован 2017-01-24 07:31:19 пользователем zabudkin
avatar
Спасибо за реакцию, но суть то как раз в том, что примерно подобным способом как у меня поисковик смотрит на контент. Важно не просто чтобы в keywords было что-то, важно чтобы то, что в кейвордс соответствовало тому что есть в контенте.
avatar
Ну что мешает добавить array_count_values? ;)
avatar
хех) Не знал про эту функцию)
avatar
Я сам удивился, что разработчики PHP напридумывали для «из коробки», особенно мне нравится php7 :) но его повсеместного внедрения ждать и ждать :(
Комментарий отредактирован 2017-01-26 04:47:15 пользователем zabudkin
avatar
Если Вы уже сделали с array_count_values, то выкладывайте :) мне просто лень тестить и постить, а вот тупо пописать как сейчас — это легко :)))))))
avatar
Во-первых не я автор топика, изменить не могу)
Во-вторых переписывать на array_count_values смысла не вижу, ибо лучшее — враг хорошего. Работает — и ладно.
Ну и последнее — если программист утром в сети, значит он ЕЩЕ в сети) У самого башка не варит)
avatar
может имелось ввиду «пока до сих пор в сети»? :))
Комментарий отредактирован 2017-01-26 05:04:05 пользователем zabudkin
avatar
угум-с)
avatar
мне всё равно лень ) «работает — не трожь» — пастулат :)))
avatar
Поисковики уже давно не учитывают кейвордс или если и учитывают, то влияние их очень минимальное.
avatar
+100500! потому расположение слов не существенно и может даже вызвать отрицальную реакцию, если встречаются реже 2 раз подряд.
avatar
я уже писал, когда идёт борьба за топ1-3, на вес — золото даже такая такая мелочь как ключевые слова.

Можно долго спорить, влияют ключевые слова или нет, проверить никто не сможет, так как алгоритмы поисковиков — мистическая штука. Нужно просто придерживаться общепринятых правил и не забывать о таких мелких штуках как — ключевые слова.

В пример могу привести ВК тематику с ВЧ запросами, подмастерье долго бился и не мог сдвинуть сайт со своих позиций: при валидности кода, адаптивности, 99% уникальным текстом, респонзивными картинками, видео, title к ссылкам, alt к картинкам, 2-3 раза упоминание на странице тега strong, идеальными мета-данными, микроразметкой. Но была упущена одна вещь — ключевые слова, которая была заполнена у конкурента, при внесении правок на сайт, он обошел конкурента. Может влияние и мизерное, но оно есть и забывать о ключевых — не стоит.
Комментарий отредактирован 2017-01-26 22:17:06 пользователем Fr3ddy
avatar
А как в плагине задать слова и символы для исключения?
avatar
а никак, попросить автора доработать плагин под Ваши нужды, не бесплатно.
Привыкайте, любая работа стоит денег :)
avatar
создайте отдельно вопрос на эту тему, больше шансов, что кто-то может вам подскажет решение
ну или сами попробуйте разобраться — вам опыт в копилку будет :)
avatar
Слова чуть выше исключали.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.