设为首页收藏本站

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 279|回复: 1

php自动文章关键字提取

[复制链接]
发表于 2013-12-13 00:48:30 | 显示全部楼层 |阅读模式
现在, 很多web系统都用到了不少的自然语言处理技术来提高客户体验.  
  主要技术:
  1. 文章关键字提取.
  2. 相关文章(产品)推荐.
  最近有不少网友问道, 这里以php为例子讲解下php的"关键字提取"的实现, 同时这个也是实现"相关文章推荐"的前提.
  基本分以下几个步骤:  


  一. 对文章进行分词:  
      php的中文分词程序还是有不少的, 从前辈的scws, 到用纯php实现的phpAnalysis, phpcws(phpcws)以及本人开发的robbe扩展.
      这里的讲解是使用"robbe分词扩展"来进行分词, robbe兴许不是最好的, 但一定是最快的.
      选择的分词器需要支持停止词过滤.

  二. 统计词条词频并且排序:  
      对一篇文章分词后, 统计每个词条出现的次数. 然后按照词频降序排序下, 你想要的结果在前面几个词中.
      前提是去除了出现词频很高的停止词, 要不然得到的都是一些无用的停止词. (类似于TF-IDF算法)


  完整的过程代码如下:
  1. <?php
  2. header('content-type:text/html;charset:utf-8');

  3. $__text__ = '';
  4. $__mode__ = 2;
  5. $__timer__ = 0;
  6. $_act = '';
  7. if ( isset($_POST['_act']) ) {
  8.         $_act = $_POST['_act'];
  9.         if ( $_act == 'split'  ) {
  10.                 $__text__ = $_POST['text'];
  11.                 $__mode__ = intval( $_POST['mode'] );

  12.                 $s_time = timer();
  13.                 $_result = rb_split($__text__, $__mode__);
  14.                
  15.                 $_keywords = array();
  16.                 foreach ( $_result as $_value ) {
  17.                         if ( is_numeric($_value) ) continue;
  18.                         if ( ord($_value) > 127 && strlen($_value) == 3 ) {
  19.                                 //$w = rb_dic_get(__RB_LEX_CJK_WORDS__, $_value);
  20.                                 //if ( $w['freq'] > 58023 ) continue;
  21.                                 continue;
  22.                         }
  23.                         if ( ! isset($_keywords[$_value]) ) $_keywords[$_value] = 1;
  24.                         else $_keywords[$_value] = $_keywords[$_value] + 1;
  25.                 }
  26.                 //Sort
  27.                 arsort($_keywords, SORT_NUMERIC);
  28.                 unset($_result);
  29.                 $_result = array();
  30.                 foreach( $_keywords as $_key => $_value ) {
  31.                         //if ( $_value <= 2 ) continue;
  32.                         $_result[$_key] = $_value;
  33.                 }
  34.                 unset($_keywords);
  35.                 $__timer__ = timer() - $s_time;
  36.         }
  37. }

  38. function timer() {
  39.         list($msec, $sec) = explode(' ', microtime());       
  40.         return ((float)$msec + (float)$sec);
  41. }
  42. ?>
  43. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  44.         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  45. <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

  46. <head>
  47.         <title>robbe分词测试程序</title>
  48.         <meta http-equiv="content-type" content="text/html;charset=utf-8" />
  49.         <style type="text/css">
  50.                 #box {width: 1000px;}
  51.                 .input-text {border: 1px solid #CCC;width: 1000px;height: 200px;background-color: #FFF;
  52.                         color: #555;font-size: 14px;}
  53.                 .link-box {overflow: hidden;zoom:1;padding-top:10px;}
  54.                 #submit-link {float:right;width:150px;height: 26px;line-height: 26px;
  55.                         background-color: #A50100;color: #FFF;font-weight: bold;text-align: center;
  56.                         text-decoration: none;font-size: 14px;}
  57.                 #info-link {float:right;width:300px;height: 26px;line-height: 26px;
  58.                         background-color: #A50100;color: #FFF;font-weight: bold;text-align: center;
  59.                         text-decoration: none;font-size: 14px;}
  60.                 .link-item {float: left;font-size: 14px;font-weight: bold;
  61.                         height: 26px;line-height: 26px;width: 100px;color: #A50100;}
  62.                 .title-item {height:30px;line-height: 30px;font-size: 14px;font-weight: bold;}
  63.         </style>
  64. </head>

  65. <body>
  66.         <div id="box">
  67.                 <div class="title-item">请输入文章内容:</div>
  68.                 <form name="robbe" method="post" action="robbe.keywords.php">
  69.                         <div class="r-item"><textarea name="text" class="input-text" id="text"><?=$__text__?></textarea></div>
  70.                         <input type="hidden" name="_act" value="split"/>
  71.                         <div class="link-box">
  72.                         <a class="link-item">
  73.                                 <input type="radio" name="mode" value="1" <?=$__mode__==1?'checked="checked"':''?>/>简易模式</a>
  74.                         <a class="link-item">
  75.                                 <input type="radio" name="mode" value="2" <?=$__mode__==2?'checked="checked"':''?>/>复杂模式</a>
  76.                         <a href="javascript:;" onclick="do_submit();return false;" id="submit-link">robbe分词</a>
  77.                 </div>
  78.                 </form>

  79.                 <?php
  80.                 if ( $_act == 'split' ) {
  81.                 ?>
  82.                 <div class="title-item">关键字相关排序:</div>
  83.                 <div><textarea class="input-text">
  84.                         <?php foreach ( $_result as $_key => $_val ) echo $_key.'['.$_val.'] ';?>
  85.                 </textarea></div>
  86.                 <?php
  87.                 }
  88.                 ?>
  89.         </div>

  90. <script type="text/javascript">
  91. String.prototype.trim = function() {return this.replace(/^\s+|\s+$/g, '');}
  92. function do_submit() {
  93.         var text = document.getElementById('text');
  94.         if ( text.value.trim() == '' ) return;
  95.         document.robbe.submit();
  96. }
  97. </script>
  98. </body>
复制代码


安装robbe扩展后, 可以直接运行该php页面了.

  测试一下:  
  以本人的一篇博客为测试例子: http://my.oschina.net/jcseg/blog/124173,  



  统计排序词频超过3的词条如下:
  缓存[13] web[9] 静态[6] 服务器[6] 负载[5] 数据库[4] 浏览器[4] 内容[4] 使用[4] 组件[4] js[4] css[4] 均衡[4] 分离[4] 压缩[4] 域名[4] 文件[4] 文案[3] 系统[3] 图片[3] 分布式[3] 方案[3] dns[3]
  效果基本还可以吧, 这篇博客确实关注的是"缓存", "数据库", "负载", "浏览器", "web". 主要关键字都提取出来了.
  想要达到更好的效果, 可能需要维护停止词库.



开源中国


 楼主| 发表于 2013-12-13 00:51:40 | 显示全部楼层

jcseg歧义句子分词测试

今天在晚上看到一些网友测试分词器常用的起义语句, 我拿jcseg去试了下:  
  1. 结婚的和尚未结婚的
jcseg分词:
结婚 的 和 尚未 结婚 的
Done, total:10, split:6, cost: 0.00026sec
  2. 他说的确实在理
jcseg分词:
他 说 的 确实 在理
Done, total:7, split:5, cost: 0.00052sec
  
3. 把手抬起来
jcseg分词:
把手 抬起 来
Done, total:5, split:3, cost: 0.00000sec

4. 邓颖超生前使用过的物品
jcseg分词:
邓颖超 生前 使用 过 的 物品
Done, total:11, split:6, cost: 0.00000sec

5. 阿拉斯加遭强暴风雪袭击致xx人死亡
jcseg分词:
阿拉斯加 遭 强暴 风雪 袭击 致 xx 人 死亡
Done, total:17, split:9, cost: 0.00052sec


6. 今后三年中将翻两番
jcseg分词:
今后 三年 中将 翻两番
Done, total:9, split:4, cost: 0.00000sec

7. 乒乓球拍卖完了
jcseg分词:
乒乓球 拍卖 完了
Done, total:7, split:3, cost: 0.00000sec

8. 粮食不卖给八路军
jcseg分词:
粮食 不 卖给 八路军
Done, total:8, split:4, cost: 0.00105sec

9. 费孝通向人大常委会提交书面报告
jcseg分词:
费孝通 向 人大常委会 提交 书面报告
Done, total:15, split:5, cost: 0.00105sec

10. 梁启超生前住在这里
jcseg分词:
梁启超 生前 住在 这里
Done, total:9, split:4, cost: 0.00000sec

11. 吴江西陵印刷厂
jcseg分词:
吴江 西陵 印刷厂
Done, total:7, split:3, cost: 0.00000sec

12. 叔叔亲了我妈妈也亲了我
jcseg分词:
叔叔 亲了 我 妈妈 也 亲了 我
   Done, total:11, split:7, cost: 0.00000sec


  机械匹配方法, 上面有些句子似乎很难得到正确的切分.

这些都是其他分词器切分结果不是很好的句子, jcseg的切分效果确实有些优势.

您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|小黑屋|BC Morning Website ( Best Deal Inc. 001 )  

GMT-8, 2025-10-25 00:17 , Processed in 0.015475 second(s), 20 queries .

Supported by Best Deal Online X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表