设为首页 收藏本站
查看: 1061|回复: 0

[经验分享] [转]用PHP简易实现中文分词

[复制链接]

尚未签到

发表于 2017-4-1 09:15:47 | 显示全部楼层 |阅读模式
<iframe align="center" marginwidth="0" marginheight="0" src="http://www.zealware.com/csdnblog336280.html" frameborder="0" width="336" scrolling="no" height="280"></iframe>  用PHP简易实现中文分词
  
文章作者:Hightman
文章来自:http://php.twomice.net/show_hdr.php?xname=BORRG11&dname=P7SRG11&xpos=7
  
hehe, 用PHP去做中文分词并不是一个太明智的举动, :p
  下面是我根据网上找的一个字典档, 简易实现的一个分词程序.
  (注: 字典档是gdbm格式, key是词 value是词频, 约4万个常用词)
  完整的程序演示及下载请参见: http://root.twomice.net/my_php4/dict/chinese_segment.php
  <?php <br />//中文分词系统简易实现办法
//切句单位:凡是ascii值//常见双字节符号:《》,。、?“”;:!¥…… %$#@^&*()[]{}|\/"'
//可以考虑加入超常见中文字:的和是不了啊(不过有特殊字比如"打的""郑和"..:p)

//计算时间
functiongetmicrotime(){
list($usec,$sec)=explode("",microtime());
return((float)$usec+(float)$sec);
}
$time_start=getmicrotime();


//词典类
classch_dictionary{
var$_id;

functionch_dictionary($fname=""){
if($fname!=""){
$this->load($fname);
}
}

//根据文件名载入字典(gdbm数据档案)
functionload($fname){
$this->_id=dba_popen($fname,"r","gdbm");
if(!$this->_id){
echo"failedtoopenthedictionary.($fname)
/n";
exit;
}
}

//根据词语返回频率,不存在返回-1
functionfind($word){
$freq=dba_fetch($word,$this->_id);
if(is_bool($freq))$freq=-1;
return$freq;
}
}

//分词类:(逆向)
//先将输入的字串正向切成句子,然后一句一句的分词,返回由词组成的数组.
classch_word_split{
var$_mb_mark_list;//常见切分句子的全角标点
var$_word_maxlen;//单个词最大可能长度(汉字字数)
var$_dic;//词典...
var$_ignore_mark;//trueorfalse

functionch_word_split(){
$this->_mb_mark_list=array(","," ","。","!","?",":","……","、","“","”","《","》","(",")");
$this->_word_maxlen=12;//12个汉字
$this->_dic=NULL;
$this->_ignore_mark=true;
}

//设定字典
functionset_dic($fname){
$this->_dic=newch_dictionary($fname);
}

functionset_ignore_mark($set){
if(is_bool($set))$this->_ignore_mark=$set;
}

//将字串切成句子再加以切分成词
functionstring_split($str,$func=""){
$ret=array();

if($func==""||!function_exists($func))$func="";

$len=strlen($str);
$qtr="";

for($i=0;$i$len;$i++){
$char=$str[$i];

if(ord($char)0xa1){
//读取到一个半角字符
if(!empty($qtr)){
$tmp=$this->_sen_split($qtr);
$qtr="";

if($func!="")call_user_func($func,$tmp);
else$ret=array_merge($ret,$tmp);
}

//如果是单词或数字.根据char将数据读取到>=0xa1为止
if($this->_is_alnum($char)){
do{
if(($i+1)>=$len)break;
$char2=substr($str,$i+1,1);
if(!$this->_is_alnum($char2))break;

$char.=$char2;
$i++;
}while(1);

if($func!="")call_user_func($func,array($char));
else$ret[]=$char;
}
elseif($char==''||$char=="/t"){
//nothing.
continue;
}
elseif(!$this->_ignore_mark){
if($func!="")call_user_func($func,array($char));
else$ret[]=$char;
}
}
else{
//双字节字符.
$i++;
$char.=$str[$i];

if(in_array($char,$this->_mb_mark_list)){
if(!empty($qtr)){
$tmp=$this->_sen_split($qtr);
$qtr="";

if($func!="")call_user_func($func,$tmp);
else$ret=array_merge($ret,$tmp);
}

if(!$this->_ignore_mark){
if($func!="")call_user_func($func,array($char));
else$ret[]=$char;
}
}
else{
$qtr.=$char;
}
}
}

if(strlen($qtr)>0){
$tmp=$this->_sen_split($qtr);

if($func!="")call_user_func($func,$tmp);
else$ret=array_merge($ret,$tmp);
}

//returnvalue
if($func==""){
return$ret;
}
else{
returntrue;
}
}

//将句子切成词,逆向
function_sen_split($sen){
$len=strlen($sen)/2;
$ret=array();

for($i=$len-1;$i>=0;$i--){
//如:这是一个分词程序

//先取得最后一个字
$w=substr($sen,$i*2,2);

//最终的词长
$wlen=1;

//开始逆向匹配到最大长度.
$lf=0;//lastfreq
for($j=1;$j$this->_word_maxlen;$j++){
$o=$i-$j;
if($o0)break;
$w2=substr($sen,$o*2,($j+1)*2);

$tmp_f=$this->_dic->find($w2);
//echo"{$i}.{$j}:$w2(f:$tmp_f)/n";
if($tmp_f>$lf){
$lf=$tmp_f;
$wlen=$j+1;
$w=$w2;
}
}
//根据$wlen将$i偏移了
$i=$i-$wlen+1;
array_push($ret,$w);
}

$ret=array_reverse($ret);
return$ret;
}

//判断字符是不是字母数字_-[0-9a-z_-]
function_is_alnum($char){
$ord=ord($char);
if($ord==45||$ord==95||($ord>=48&&$ord57))
returntrue;
if(($ord>=97&&$ord122)||($ord>=65&&$ord90))
returntrue;
returnfalse;
}
}


//分词后的回调函数
functioncall_back($ar){
foreach($aras$tmp){
echo$tmp."";
//flush();
}
}

//实例(如果没有输入就从sample.txt中读取):
$wp=newch_word_split();
$wp->set_dic("dic.db");

if(!isset($_REQUEST['testdat'])||empty($_REQUEST['testdat'])){
$data=file_get_contents("sample.txt");
}
else{
$data=&$_REQUEST['testdat'];
}

//output
echo"简易分词演示
/n";
echo"/n";
echo"分词结果(".strlen($data)."chars):
/n/n";

//设定是否忽略不返回分词符号(标点,常用字)
$wp->set_ignore_mark(false);

//执行切分,如果没有设置callback函数,则返回由词组成的array
$wp->string_split($data,"call_back");

$time_end=getmicrotime();
$time=$time_end-$time_start;

echo"
/n本次分词耗时:$timeseconds
/n";
?>


您也可以在下面文本框中输入文字,提交后试验分词效果:






附:

本程序源码:chinese_segment.php(简易实现方式)

需要的字典:dic.db(gdbm格式)


  
附:
(简易中文分词实现完整代码及字典下载)
http://php.twomice.net/show_hdr.php?xname=BORRG11&dname=P7SRG11&xpos=19
(C版简易中文分词服务程序(cscwsd))
http://php.twomice.net/show_hdr.php?xname=BORRG11&dname=P7SRG11&xpos=40

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-358428-1-1.html 上篇帖子: PHP Webservice的发布与调用 下篇帖子: [转]php函数的传址调用
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

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