php中文分词插件phpanalysis、结巴、SCWS对比

php中文分词插件phpanalysis、结巴、SCWS对比

php中文分词插件phpanalysis、结巴、SCWS对比

今天来介绍一下三款php的中文分词插件,每一款都有自己的特色,满足不同的业务需求。

一、phpanalysis

PHPAnalysis分词程序使用居于unicode的词库,使用反向匹配模式分词,理论上兼容编码更广泛,并且对utf-8编码尤为方便。 由于PHPAnalysis是无组件的系统,因此速度会比有组件的稍慢,不过在大量分词中,由于边分词边完成词库载入,因此内容越多,反而会觉得速度越快,这是正常现象,PHPAnalysis的词库是用一种类似哈希(Hash)的数据结构进行存储的,因此对于比较短的字符串分词,只需要占极小的资源,比那种一次性载入所有词条的实际性要高得多,并且词库容量大小不会影响分词执行的速度。

点击下载phpanalysis2.0.zip

下载后解压将此目录放在web目录下,访问demo.php

php中文分词插件phpanalysis、结巴、SCWS对比

<?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>


效果如下

php中文分词插件phpanalysis、结巴、SCWS对比

二、结巴中文分词

jieba(结巴)中文分词是目前国内一款较好的中文分词插件。
1.兼容当前绝大部分流行开发语言,例:Java、C/C++、PHP、Ios、 Node.js 等开发语言。
2.搜索引擎模式,全模式和精确模式匹配,以及关键词提取的实用性的功能
3.代码开源,词库自定义等优势
4.对GBK不是特别友好、需要转译一次;中英文分词兼容性不是很好;词库更新较缓慢,如果是长期的分词使用,需要频繁更新词库。

点击下载jieba-php.zip

下载后解压后将目录放在web目录下,访问demo.php

php中文分词插件phpanalysis、结巴、SCWS对比

<?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/>";
?>



访问后效果如下

php中文分词插件phpanalysis、结巴、SCWS对比


三、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中文分词插件phpanalysis、结巴、SCWS对比

<?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();
?>


访问后效果

php中文分词插件phpanalysis、结巴、SCWS对比

注意:如果显示乱码,请将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");
    }
?>

执行完后

php中文分词插件phpanalysis、结巴、SCWS对比

我们可以发现,速度上phpanalysis最快,耗时0.005s内存消耗也最小 128kb

jieba的速度最慢,内存消耗最大

scws也挺快的

php中文分词插件phpanalysis、结巴、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还要快,但是效果却是最差的,诚招都拆分了,明明是一个词,水平和被拆分成水和平和

php中文分词插件phpanalysis、结巴、SCWS对比

php中文分词插件phpanalysis、结巴、SCWS对比

五、总结

分词质量与速度上综合评估,还是phpanalysis比较优秀,消耗内存少,速度也比较快



{{collectdata}}

网友评论0