Облако тегов

Сегодня будем рассматривать такую задачку как генерация облака тегов. Мы все конечно ни раз встречали это облако на других сайтах и блогах, но не все задумывались над реализацией этого облака на php. Общие моменты ясны из определения с wiki:

“визуальное представление списка ярлыков (или категорий). Частота упоминаний, поисков, ссылок в интернете с определенного сайта неких слов, терминов, имен, отображается на специальной странице в виде изображения этих слов в формате гиперссылок. Размер изображения тем больше, чем выше релевантность данного слова (термина, имени).”

Релевантность в нашем случае определяется количеством вхождений одного тега в их общую массу.

Учитывая все вышесказанное, весь алгоритм построения облака тегов можно разделить на два этапа:

  1. Генерация списка пар Тег-Количество вхождений
  2. Вывод облака с учетом релевантности тегов

Первая задача решается довольно просто с технической точки зрения. Вторая тоже, но здесь возможны вариации.

Ниже приведу небольшой класс, который я написал для генерации облака тегов.

<?
class TagsCloud {

	private $tags;

	private $font_size_min = 14;
	private $font_size_step = 5;

	function __construct($tags) {

		shuffle($tags);
		$this->tags = $tags;	

	}

	private function get_tag_count($tag_name, $tags) {

		$count = 0;

		foreach ($tags as $tag) {
			if ($tag == $tag_name) {
				$count++;
			}
		}

		return $count;

	}

	private function tagscloud($tags) {

		$tags_list = array();

		foreach ($tags as $tag) {
			$tags_list[$tag] = self::get_tag_count($tag, $tags);
		}

		return $tags_list;		

	}

	private function get_min_count($tags_list) {

		$min = $tags_list[$this->tags[0]];

		foreach ($tags_list as $tag_count) {

			if ($tag_count < $min) $min = $tag_count;

		}

		return $min;

	}

	public function get_cloud() {

		$cloud = Array();

		$tags_list = self::tagscloud($this->tags);
		$min_count = self::get_min_count($tags_list);

		foreach ($tags_list as $tag=>$count) {

			$font_steps = $count - $min_count;
			$font_size = $this->font_size_min + $this->font_size_step * $font_steps;

			$cloud[] = "<span style='font-size:".$font_size."px'>".$tag."</span>";
		}

		return $cloud;

	}
}
?>

Скачать этот класс можно здесь: tagscloud.php, а работать с этим классом примерно так:

<?

$tags = array(
	'ajax', 'javascript', 'php', 'dojo',
	'ajax', 'jquery', 'seo', 'seo',
	'php', 'blog', 'ajax', 'php',
	'html', 'css', 'ajax', 'javascript',
	'css', 'jquery', 'php', 'smo'
);

$mycloud   = new TagsCloud($tags);
$tags_list = $mycloud->get_cloud();

foreach ($tags_list as $tag) {
	echo $tag.' ';
}

?>

В результате работы этого примера в окне браузера Вы получите следующее:

Второй этап построения облака тегов (вывод облака) заключается в преобразовании показателя релевантности (кол-во вхождений) в размер шрифта результирующей надписи.

В классе я реализовал это следующим образом: в настройках задается минимальный размер шрифта, который соответствует минимальному уровню релевантности (одно вхождение). Все теги с большей релевантностью имеют размер на столько пикселей больше, на сколько больше они имеют вхождений. Шаг изменения можно задавать полем font_size_step, а минимальный размер шрифта полем font_size_min.

Для дальнейшего усовершенствования внешнего вида можно прикрутить облако к небольшому js-скрипту. В результате чего получится такое облако: http://nacmnogo.ru/cloud.html. Подробнее про этот скрипт можно почитать здесь http://habrahabr.ru/blogs/javascript/38264/.

Что ж. У меня все. Удачи!




Читайте также:



 #  #  #  #  #  #  #  #  #  #

19 Ответов на “Облако тегов”

  1. DeveloperGuru.NET
    Сентябрь 1st, 2008

    При такой реализации наличие очень популярного тега приведет к тому, что все остальные теги будут отображены одним шрифтом.

  2. cryptus
    Сентябрь 2nd, 2008

    Думал про этот баг, но для решения этой задачи в голову приходит только нелинейная зависимость между размером шрифта и уровнем релевантности. Например логарифм натуральный. :)

  3. mr.Hide
    Сентябрь 2nd, 2008

    ууу до решения таких задачек мне еще рано. что-нибудь попроще бы, это да…..

  4. Антон
    Сентябрь 2nd, 2008

    Классное облако, эффект 3D поражает. Респектище

  5. cryptus
    Сентябрь 2nd, 2008

    Да. Респект чуваку, который написал этот плагин на js :)

  6. cryptus
    Сентябрь 2nd, 2008

    2 mr. Hide: Ну это только звучит сложно. На деле – пара строк :)

  7. mr.Hide
    Сентябрь 3rd, 2008

    ну…. как знать) я сча думаю как писать свой дорген)

  8. DeveloperGuru.NET
    Сентябрь 3rd, 2008

    Решается с помощью кластерного анализа. В двух словах: все теги разбиваются на заданные группы (кластеры) в соответствии их частотности. Теги из одной группы отображаются одним шрифтом.
    Очень популярный тег попадет в отдельную группу, но остальные группы при этом не пострадают.
    Подробнее на английском и реализация:
    http://i-novice.net/gout/DkIQRQgcSw0LQ14BUh1CBAFQUFcXW0dBF11STQNYFwcKWQMaRlIDSQZcWBBTHlQRE0ReVQBcUEsXUUMPCg==/

    Я подобный алгоритм сделал на asp.net, если кому надо – обращайтесь.

  9. cryptus
    Сентябрь 4th, 2008

    Спасибо за линк и за новую тему для размышлений :) В посте рассмотрен алгоритм K-средних, где известно заранее кол-во кластеров, которые получатся в результате – самое то, для облака тегов. Но все равно хочется попробывать реализовать какой-нибудь алгоритм с другими исходными данными, поэтому постараюсь к этой теме вернуться еще в этом блоге :)

  10. alex
    Сентябрь 15th, 2008

    честно говоря, никогда не задумывался какими методам это достигается)
    вот они, азы Веб 2.0 :)

  11. dobs
    Сентябрь 19th, 2008

    foreach ($tags_list as $tag) {
    echo $tag.’ ‘;
    }

    } – лишнее закрытие…

  12. cryptus
    Сентябрь 19th, 2008

    Спасибо, исправил. :)

  13. gorcer
    Январь 21st, 2009

    Спасибо, позновательно. Попробую в своей теме использовать это.

  14. klml
    Февраль 10th, 2009

    Спасибо огромное, с вашего позволения использую это у себя на сайте.

  15. Дмитрий
    Август 30th, 2009

    Алгоритм страшный, почему не сделать вот так:

    private function tagscloud($tags) {
    $tags_list = array();

    foreach ($tags as $tag) {
    if(!isset($tags_list[$tag])) {
    $tags_list[$tag] = 1;
    }
    else {
    $tags_list[$tag] += 1;
    }
    }

    return $tags_list;
    }
    Работает быстрее и выглядит понятнее.

  16. cryptus
    Август 30th, 2009

    2 Дмитрий: Лучше на примере показать почему такая версия не будет работать.
    Допустим есть 3 слова – Картошка (1), Макароны(2) и Телефон(20). В скобках указано кол-во вхождений.
    После преобразования этих чисел в размеры шрифтов с сохранением пропорций мы можем получить 2 слова мелким, почти неразличимым, шрифтом и одно большим шрифтом.

  17. Petrik
    Октябрь 28th, 2009

    Я как сделать, если при добавлении поста, новости и т.д., в строку через запятую вводить тэги, добавлять в БД, но если совпадения, не предпринимать действий.

  18. Андриус
    Январь 17th, 2010

    А можно пример вбивания тегов в базу, с отрезанием запятулек и грамотным запросом к бд ?

  19. Tapac
    Февраль 12th, 2010

    Как-то очень много возни с генерацией тег => кол-во.
    Почему бы не воспользоваться функцией array-count-values (http://i-novice.net/gout/DkIQRQgcSxMSRxkVX0MbDwZCHlkCWkBZVRZSDElQTQsFQg1aXB0FFhdRTkhUXEAPFxtHVQ9BUEsXSV8STw==/.
    Тогда всё сведётся к
    private function tagscloud($tags) {
    return array-count-values(tags);
    }

    Ну и поиск min/max – оптимально – отсортировать по кол-ву
    через asort и взять первый и последний элементы

Оставить комментарий


© 2008 - 2010 i-novice.net | Все права защищены.