基于Tags实现内容推荐的方法(代码)
本篇文章给大家带来的内容是关于基于Tags实现内容推荐的方法(代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。
原来为了简单方便,自己小网站上的文章页的相关内容推荐就是从数据库里随机抽取数据来填充一个列表,所以一点相关性都没有,更本没有办法引导用户去访问推荐内容。
算法选择
如何能做到相似内容的推荐呢,碍于小网站还跑在虚拟主机上(对的,连一个自己完整可控的服务器都没有),所以可以想的办法不多,条件限制在 只能用PHP+MySql。所以我想到的办法就是通过Tags来匹配相似文章进行推荐。如果两篇文章的TAGS 比较相似
比如:文章A 的TAGS为: [A,B,C,D,E]文章B 的 TAGS 为:[A,D,E,F,G]
文章C 的 TAGS 为:[C,H,I,J,K]
通过眼睛我们能很方便的发现,文章B和文章A更为相似,因为它们有三个关键字相同分别为:[A,D,E],哪如何用计算机来判断它们的相似度呢,这里我们用jaccard相似度的最基本应用来计算它们的相似度
jaccard相似度
给定两个集合A,B,Jaccard 系数定义为A与B交集的大小与A与B并集的大小的比值,定义如下:
文章A和文章B的交集为 [A,D,E],大小为3,并集为[A,B,C,D,E,F,G],大小为7,3/7=0.4285...
而文章A和文章C交集为 [C],大小为1,并集为[A,B,C,D,E,H,I,J,K],大小为9, 1/9=0.11111...
这样就可以得出文章A,B比文章A,C更为相似,有了这个算法,计算机就可以来判断两篇文章的相似度了。
具体的推荐思想
给定一篇文章,获取该文章的关键字TAGS,然后通过以上算法去数据库比对所有文章的相似度,获取最相似的N篇文章进行推荐。
实现过程
第一 TAGS的获取
文章的TAGS是通过TF-IDF算法,提取文章中的高频词,选取N个作为TAGS,对于中文的文章来说还涉及到一个中文分词的问题,因为是虚拟主机的关系,这步的工作我用python(为什么用Python ,jieba分词,真香)在本地写了一个程序,完成所有文章的分词,词频统计,生成TAGS,并写回服务器的数据库。由于本文是写推荐的算法,所以分词和建立TAGS的部分就不具体展开了,而且不同的系统有不同的TAGS建立方式。
第二 TAGS的存储
建立两张表,用于存储TAGS
tags,用于存所有tag的名称
+-------+------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+------------+------+-----+---------+-------+ | tag | text | YES | | NULL | | | count | bigint(20) | YES | | NULL | | | tagid | int(11) | NO | PRI | 0 | | +-------+------------+------+-----+---------+-------+
tag_map 建立tag和文章的映身关系。
+-----------+------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-----------+------------+------+-----+---------+-------+ | id | bigint(20) | NO | PRI | 0 | | | articleid | bigint(20) | YES | | NULL | | | tagid | int(11) | YES | | NULL | | +-----------+------------+------+-----+---------+-------+
tag_map存的数据类似如下:
+----+-----------+-------+ | id | articleid | tagid | +----+-----------+-------+ | 1 | 776 | 589 | | 2 | 776 | 471 | | 3 | 776 | 1455 | | 4 | 776 | 1287 | | 5 | 776 | 52 | | 6 | 777 | 1386 | | 7 | 777 | 588 | | 8 | 777 | 109 | | 9 | 777 | 603 | | 10 | 777 | 1299 | +----+-----------+-------+
其实做相似推荐的时候,只需要用到tag_map表就可以了,因为tagid和tag name 是一一对应的。
具体编码
1.获取所有文章对应的TAGID
mysql> select articleid, GROUP_CONCAT(tagid) as tags from tag_map GROUP BY articleid; +-----------+--------------------------+ | articleid | tags | +-----------+--------------------------+ | 12 | 1178,1067,49,693,1227 | | 13 | 196,2004,2071,927,131 | | 14 | 1945,713,1711,2024,49 | | 15 | 35,119,9,1,1180 | | 16 | 1182,1924,2200,181,1938 | | 17 | 46,492,414,424,620 | | 18 | 415,499,153,567,674 | | 19 | 1602,805,691,1613,194 | | 20 | 2070,1994,886,575,1149 | | 21 | 1953,1961,1534,2038,1393 | +-----------+--------------------------+
通过以上SQL,可以一次性查询所用文章,极其对应的所有tag
在PHP,我们可以把tags变成数组。
public function getAllGroupByArticleId(){ //缓存查询数据,因为这个是全表数据,而且不更新文章不会变化,便是每次推荐都要从数据库里获取一次数据,对性能肯定会有影响,所以做个缓存。 if($cache = CacheHelper::getCache()){ return $cache; } $query_result = $this->query('select articleid, GROUP_CONCAT(tagid) as tags from tag_map GROUP BY articleid'); $result = []; foreach($query_result as $key => $value){ //用articleid 做key ,值是该id下的所有tagID数组。 $result[$value['articleid']] = explode(",",$value['tags']); } CacheHelper::setCache($result, 86400); return $result; }
有了这个的返回结果,就比较好办了,接下去的工作就是去应用jaccard相似度这个算法了,具体就看代码吧。
/** * [更据指定文章返回相似的文章推荐] * @param $articleid 指定的文章ID * @param $top 要返回的推荐条数 * @return Array 推荐条目数组 */ function getArticleRecommend($articleid, $top = 5){ if($cache = CacheHelper::getCache()){ return $cache; } try{ $articleid = intval($articleid); $m = new TagMapModel(); $all_tags = $m->getAllGroupByArticleId();//调用上面的函数返回所有文章的tags $finded = $all_tags[$articleid];//因为上面是包含所有文章了,所以肯定包含了当前文章。 unset($all_tags[$articleid]);//把当前文章从数组中删除,不然自己和自己肯定是相似度最高了。 $jaccard_arr = []; //用于存相似度 foreach ($all_tags as $key => $value) { $intersect =array_intersect($finded, $value); //计算交集 $union = array_unique(array_merge($finded, $value)); //计算并集 $jaccard_arr[$key] = (float)(count($intersect) / count($union)); } arsort($jaccard_arr); //按相似度排序,最相似的排最前面 $jaccard_keys = array_keys($jaccard_arr);//由于数组的key就是文章id,所以这里把key取出来就可以了 array_splice($jaccard_keys, $top);//获取前N条推荐 //到这里我们就已经得到了,最相似N篇文章的ID了,接下去的工作就是通过这几个ID,从数据库里把相关信息,查询出来就可以了 $articleModels = new \Api\Model\ArticleModel(); $recommendArticles = $articleModels->getRecommendByTag($jaccard_keys); CacheHelper::setCache($recommendArticles, 604800); //缓存7天 return $recommendArticles; } catch (\Exception $e) { throw new \Exception("获取推荐文章错误"); } }
相关推荐:
以上是基于Tags实现内容推荐的方法(代码)的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

MySQL 数据库中,用户和数据库的关系通过权限和表定义。用户拥有用户名和密码,用于访问数据库。权限通过 GRANT 命令授予,而表由 CREATE TABLE 命令创建。要建立用户和数据库之间的关系,需创建数据库、创建用户,然后授予权限。

数据集成简化:AmazonRDSMySQL与Redshift的零ETL集成高效的数据集成是数据驱动型组织的核心。传统的ETL(提取、转换、加载)流程复杂且耗时,尤其是在将数据库(例如AmazonRDSMySQL)与数据仓库(例如Redshift)集成时。然而,AWS提供的零ETL集成方案彻底改变了这一现状,为从RDSMySQL到Redshift的数据迁移提供了简化、近乎实时的解决方案。本文将深入探讨RDSMySQL零ETL与Redshift集成,阐述其工作原理以及为数据工程师和开发者带来的优势。

要填写 MySQL 用户名和密码,请:1. 确定用户名和密码;2. 连接到数据库;3. 使用用户名和密码执行查询和命令。

MySQL适合初学者使用,因为它安装简单、功能强大且易于管理数据。1.安装和配置简单,适用于多种操作系统。2.支持基本操作如创建数据库和表、插入、查询、更新和删除数据。3.提供高级功能如JOIN操作和子查询。4.可以通过索引、查询优化和分表分区来提升性能。5.支持备份、恢复和安全措施,确保数据的安全和一致性。

1.使用正确的索引索引通过减少扫描的数据量来加速数据检索select*fromemployeeswherelast_name='smith';如果多次查询表的某一列,则为该列创建索引如果您或您的应用根据条件需要来自多个列的数据,则创建复合索引2.避免选择*仅选择那些需要的列,如果您选择所有不需要的列,这只会消耗更多的服务器内存并导致服务器在高负载或频率时间下变慢例如,您的表包含诸如created_at和updated_at以及时间戳之类的列,然后避免选择*,因为它们在正常情况下不需要低效查询se

数据库ACID属性详解ACID属性是确保数据库事务可靠性和一致性的一组规则。它们规定了数据库系统处理事务的方式,即使在系统崩溃、电源中断或多用户并发访问的情况下,也能保证数据的完整性和准确性。ACID属性概述原子性(Atomicity):事务被视为一个不可分割的单元。任何部分失败,整个事务回滚,数据库不保留任何更改。例如,银行转账,如果从一个账户扣款但未向另一个账户加款,则整个操作撤销。begintransaction;updateaccountssetbalance=balance-100wh

MySQL数据库性能优化指南在资源密集型应用中,MySQL数据库扮演着至关重要的角色,负责管理海量事务。然而,随着应用规模的扩大,数据库性能瓶颈往往成为制约因素。本文将探讨一系列行之有效的MySQL性能优化策略,确保您的应用在高负载下依然保持高效响应。我们将结合实际案例,深入讲解索引、查询优化、数据库设计以及缓存等关键技术。1.数据库架构设计优化合理的数据库架构是MySQL性能优化的基石。以下是一些核心原则:选择合适的数据类型选择最小的、符合需求的数据类型,既能节省存储空间,又能提升数据处理速度

通过以下命令查看 MySQL 数据库:连接到服务器:mysql -u 用户名 -p 密码运行 SHOW DATABASES; 命令获取所有现有数据库选择数据库:USE 数据库名;查看表:SHOW TABLES;查看表结构:DESCRIBE 表名;查看数据:SELECT * FROM 表名;
