php中文分词插件phpanalysis、结巴、SCWS对比
今天来介绍一下三款php的中文分词插件,每一款都有自己的特色,满足不同的业务需求。
一、phpanalysis
PHPAnalysis分词程序使用居于unicode的词库,使用反向匹配模式分词,理论上兼容编码更广泛,并且对utf-8编码尤为方便。 由于PHPAnalysis是无组件的系统,因此速度会比有组件的稍慢,不过在大量分词中,由于边分词边完成词库载入,因此内容越多,反而会觉得速度越快,这是正常现象,PHPAnalysis的词库是用一种类似哈希(Hash)的数据结构进行存储的,因此对于比较短的字符串分词,只需要占极小的资源,比那种一次性载入所有词条的实际性要高得多,并且词库容量大小不会影响分词执行的速度。
下载后解压将此目录放在web目录下,访问demo.php
<?php // 严格开发模式 ini_set('display_errors', 'On'); ini_set('memory_limit', '64M'); error_reporting(E_ALL); $t1 = $ntime = microtime(true); $endtime = '未执行任何操作,不统计!'; function print_memory($rc, &$infostr) { global $ntime; $cutime = microtime(true); $etime = sprintf('%0.4f', $cutime - $ntime); $m = sprintf('%0.2f', memory_get_usage()/1024/1024); $infostr .= "{$rc}: {$m} MB 用时:{$etime} 秒<br />\n"; $ntime = $cutime; } header('Content-Type: text/html; charset=utf-8'); $memory_info = ''; print_memory('没任何操作', $memory_info); require_once 'phpanalysis.class.php'; $str = (isset($_POST['source']) ? $_POST['source'] : ''); $loadtime = $endtime1 = $endtime2 = $slen = 0; $do_fork = $do_unit = true; $do_multi = $do_prop = $pri_dict = false; if($str != '') { //岐义处理 $do_fork = empty($_POST['do_fork']) ? false : true; //新词识别 $do_unit = empty($_POST['do_unit']) ? false : true; //多元切分 $do_multi = empty($_POST['do_multi']) ? false : true; //词性标注 $do_prop = empty($_POST['do_prop']) ? false : true; //是否预载全部词条 $pri_dict = empty($_POST['pri_dict']) ? false : true; $tall = microtime(true); //初始化类 PhpAnalysis::$loadInit = false; $pa = new PhpAnalysis('utf-8', 'utf-8', $pri_dict); print_memory('初始化对象', $memory_info); //载入词典 $pa->LoadDict(); print_memory('载入基本词典', $memory_info); //执行分词 $pa->SetSource($str); $pa->differMax = $do_multi; $pa->unitWord = $do_unit; $pa->StartAnalysis( $do_fork ); print_memory('执行分词', $memory_info); $okresult = $pa->GetFinallyResult(' ', $do_prop); print_memory('输出分词结果', $memory_info); $pa_foundWordStr = $pa->foundWordStr; $t2 = microtime(true); $endtime = sprintf('%0.4f', $t2 - $t1); $slen = strlen($str); $slen = sprintf('%0.2f', $slen/1024); $pa = ''; } $teststr = "2010年1月,美国国际消费电子展 (CES)上,联想将展出一款基于ARM架构的新产品,这有可能是传统四大PC厂商首次推出的基于ARM架构的消费电子产品,也意味着在移动互联网和产业融合趋势下,传统的PC芯片霸主英特尔正在遭遇挑战。 11月12日,联想集团副总裁兼中国区总裁夏立向本报证实,联想基于ARM架构的新产品正在筹备中。 英特尔新闻发言人孟轶嘉表示,对第三方合作伙伴信息不便评论。 正面交锋 ARM内部人士透露,11月5日,ARM高级副总裁lanDrew参观了联想研究院,拜访了联想负责消费产品的负责人,进一步商讨基于ARM架构的新产品。ARM是英国芯片设计厂商,全球几乎95%的手机都采用ARM设计的芯片。 据悉,这是一款采用高通芯片(基于ARM架构)的新产品,高通产品市场总监钱志军表示,联想对此次项目很谨慎,对于产品细节不方便透露。 夏立告诉记者,联想研究院正在考虑多种方案,此款基于ARM架构的新产品应用邻域多样化,并不是替代传统的PC,而是更丰富的满足用户的需求。目前,客户调研还没有完成,“设计、研发更前瞻一些,最终还要看市场、用户接受程度。”"; ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>分词测试</title> </head> <body> <table width='90%' align='center'> <tr> <td> <hr size='1' /> <form id="form1" name="form1" method="post" action="?ac=done" style="margin:0px;padding:0px;line-height:24px;"> <b>源文本:</b> <a href="dict_build_new.php" target="_blank">[更新词典]</a> <br/> <textarea name="source" style="width:98%;height:150px;font-size:14px;"><?php echo (isset($_POST['source']) ? $_POST['source'] : $teststr); ?></textarea> <br/> <input type='checkbox' name='do_fork' value='1' <?php echo ($do_fork ? "checked='1'" : ''); ?>/>岐义处理 <input type='checkbox' name='do_unit' value='1' <?php echo ($do_unit ? "checked='1'" : ''); ?>/>新词识别 <input type='checkbox' name='do_multi' value='1' <?php echo ($do_multi ? "checked='1'" : ''); ?>/>多元切分 <input type='checkbox' name='do_prop' value='1' <?php echo ($do_prop ? "checked='1'" : ''); ?>/>词性标注 <input type='checkbox' name='pri_dict' value='1' <?php echo ($pri_dict ? "checked='1'" : ''); ?>/>预载全部词条 <br/> <input type="submit" name="Submit" value="提交进行分词" /> <input type="reset" name="Submit2" value="重设表单数据" /> </form> <br /> <textarea name="result" id="result" style="width:98%;height:120px;font-size:14px;color:#555"><?php echo (isset($okresult) ? $okresult : ''); ?></textarea> <br /><br /> <b>调试信息:</b> <hr /> <font color='blue'>字串长度:</font><?php echo $slen; ?>K <font color='blue'>自动识别词:</font><?php echo (isset($pa_foundWordStr)) ? $pa_foundWordStr : ''; ?><br /> <hr /> <font color='blue'>内存占用及执行时间:</font>(表示完成某个动作后正在占用的内存)<hr /> <?php echo $memory_info; ?> 总用时:<?php echo $endtime; ?> 秒 </td> </tr> </table> </body> </html>
效果如下
二、结巴中文分词
jieba(结巴)中文分词是目前国内一款较好的中文分词插件。点击下载jieba-php.zip,
下载后解压后将目录放在web目录下,访问demo.php
<?php //设置PHP运行占用内存 ini_set('memory_limit', '1024M'); //导入文件 require_once "vendor/multi-array/MultiArray.php"; require_once "vendor/multi-array/Factory/MultiArrayFactory.php"; require_once "class/Jieba.php"; require_once "class/Finalseg.php"; use Fukuball\Jieba\Jieba; use Fukuball\Jieba\Finalseg; Jieba::init(); Finalseg::init(); echo "<pre/>"; $seg_list = Jieba::cut("结巴中文分词:做最好的中文分词!"); var_dump($seg_list); echo "<hr/>"; $seg_list = Jieba::cut("结巴分词-全模式分词", true); var_dump($seg_list); #全模式 echo "<hr/>"; $seg_list = Jieba::cut("默认就是精确模式", false); var_dump($seg_list); #默認精確模式 echo "<hr/>"; $seg_list = Jieba::cutForSearch("搜索引擎模式,会将这句话分词成功类似搜索引擎的模式"); #搜索引擎模式 var_dump($seg_list); echo "<hr/>"; ?>
访问后效果如下
三、SCWS
SCWS 是 Simple Chinese Word Segmentation 的首字母缩写(即:简易中文分词系统)。
这是一套基于词频词典的机械式中文分词引擎,它能将一整段的中文文本基本正确地切分成词。 词是中文的最小语素单位,但在书写时并不像英语会在词之间用空格分开, 所以如何准确并快速分词一直是中文分词的攻关难点。
SCWS 采用纯 C 语言开发,不依赖任何外部库函数,可直接使用动态链接库嵌入应用程序, 支持的中文编码包括 GBK、UTF-8 等。此外还提供了 PHP 扩展模块, 可在 PHP 中快速而方便地使用分词功能。
分词算法上并无太多创新成分,采用的是自己采集的词频词典,并辅以一定的专有名称,人名,地名, 数字年代等规则识别来达到基本分词,经小范围测试准确率在 90% ~ 95% 之间, 基本上能满足一些小型搜索引擎、关键字提取等场合运用。首次雏形版本发布于 2005 年底。
点击下载pscws4utf8.zip,官网提供的是gbk版本的,我改为了utf-8版本,可以直接运行
解压后放到web目录,访问demo.php
<?php //test.php // // Usage on command-line: php test.php <file|textstring> // Usage on web: error_reporting(E_ALL); //名字允许复查? $text = <<<EOF 中国航天官员应邀到美国与太空总署官员开会 发展中国家 上海大学城书店 表面的东西 今天我买了一辆面的,于是我坐着面的去上班 化妆和服装 这个门把手坏了,请把手拿开 将军任命了一名中将,产量三年中将增长两倍 王军虎去广州了,王军虎头虎脑的 欧阳明练功很厉害可是马明练不厉害 毛泽东北京华烟云 人中出吕布 马中出赤兔Q1,中我要买Q币充值 EOF; // require 'pscws4.class.php'; $cws = new PSCWS4('utf8'); $cws->set_dict('etc/dict.utf8.xdb'); $cws->set_rule('etc/rules.utf8.ini'); //$cws->set_multi(3); //$cws->set_ignore(true); $cws->set_debug(true); //$cws->set_duality(true); $cws->send_text($text); //if (php_sapi_name() != 'cli') header('Content-Type: text/plain'); echo "pscws version: " . $cws->version() . "\n"; echo "Segment result:\n\n"; while ($tmp = $cws->get_result()) { $line = ''; foreach ($tmp as $w) { if ($w['word'] == "\r") continue; if ($w['word'] == "\n") $line = rtrim($line, ' ') . "\n"; //else $line .= $w['word'] . "/{$w['attr']} "; else $line .= $w['word'] . " "; } echo $line; } // top: echo "Top words stats:\n\n"; $ret = array(); $ret = $cws->get_tops(10,'r,v,p'); echo "No.\tWord\t\t\tAttr\tTimes\tRank\n------------------------------------------------------\n"; $i = 1; foreach ($ret as $tmp) { printf("%02d.\t%-16s\t%s\t%d\t%.2f\n", $i++, $tmp['word'], $tmp['attr'], $tmp['times'], $tmp['weight']); } $cws->close(); ?>
访问后效果
注意:如果显示乱码,请将demo.php的头部加入header("Content-type: text/html; charset=utf-8");
四、速度和分词质量对比
编写一个简单的分词
<?php function Test($good) { BoDebug::TickStart("PscwsSeg"); var_dump(\Plugin\Splitword\PscwsSeg::Cut("js中for用法")); BoDebug::TickStop("PscwsSeg"); BoDebug::TickStart("JiebaSeg"); var_dump(\Plugin\Splitword\JiebaSeg::Cut("js中for用法")); BoDebug::TickStop("JiebaSeg"); BoDebug::TickStart("PhpanaSeg"); var_dump(\Plugin\Splitword\PhpanaSeg::Cut("js中for用法")); BoDebug::TickStop("PhpanaSeg"); } ?>执行完后
我们可以发现,速度上phpanalysis最快,耗时0.005s内存消耗也最小 128kb
jieba的速度最慢,内存消耗最大
scws也挺快的
分词效果,三者一样
下面我们再看看长文本分词
<?php function Test($good) { $str = "BFW为技术爱好者学习交流提供一个免费的场所,非公司性质,旨在推动原创互联网技术交流,提升国人的技术水平和工作效率,现诚招原创技术写作人员一起努力为技术创作留下自己的笔迹,有意者请注册进行技术博客写作。"; BoDebug::TickStart("PscwsSeg"); print_r(\Plugin\Splitword\PscwsSeg::Cut($str)); echo "<br/>"; BoDebug::TickStop("PscwsSeg"); BoDebug::TickStart("JiebaSeg"); print_r(\Plugin\Splitword\JiebaSeg::Cut($str)); echo "<br/>"; BoDebug::TickStop("JiebaSeg"); BoDebug::TickStart("PhpanaSeg"); print_r(\Plugin\Splitword\PhpanaSeg::Cut($str)); BoDebug::TickStop("PhpanaSeg"); } ?>执行完我们看到scws的速度最快0.021s,比phpanalysis还要快,但是效果却是最差的,诚招都拆分了,明明是一个词,水平和被拆分成水和平和
五、总结
分词质量与速度上综合评估,还是phpanalysis比较优秀,消耗内存少,速度也比较快
网友评论0