찾다
php教程php手册用PHP简易实现中文分词

中文

hehe, 用PHP去做中文分词并不是一个太明智的举动, :p

下面是我根据网上找的一个字典档, 简易实现的一个分词程序.

(注: 字典档是gdbm格式, key是词 value是词频, 约4万个常用词)

完整的程序演示及下载请参见: http://root.twomice.net/my_php4/dict/chinese_segment.php

//中文分词系统简易实现办法
//切句单位:凡是ascii值//常见双字节符号:《》,。、?“”;:!¥…… %$#@^&*()[]{}|\/"'
//可以考虑加入超常见中文字: 的 和 是 不 了 啊 (不过有特殊字比如 "打的" "郑和" .. :p)

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


//词典类
class ch_dictionary {
    var $_id;

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

    // 根据文件名载入字典 (gdbm数据档案)
    function load($fname) {
        $this->_id = dba_popen($fname, "r", "gdbm");
        if (!$this->_id) {
            echo "failed to open the dictionary.($fname)
\n";
            exit;
        }
    }

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

// 分词类: (逆向)
// 先将输入的字串正向切成句子, 然后一句一句的分词, 返回由词组成的数组.
class ch_word_split {
    var $_mb_mark_list;    // 常见切分句子的全角标点
    var $_word_maxlen;    // 单个词最大可能长度(汉字字数)
    var $_dic;        // 词典...
    var $_ignore_mark;    // true or false
   
    function ch_word_split () {
        $this->_mb_mark_list = array(","," ","。","!","?",":","……","、","“","”","《","》","(",")");
        $this->_word_maxlen  = 12;    // 12个汉字
        $this->_dic = NULL;
        $this->_ignore_mark = true;
    }

    // 设定字典
    function set_dic($fname) {
        $this->_dic = new ch_dictionary($fname);
    }

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

    // 将字串切成句子再加以切分成词
    function string_split($str, $func = "") {       
        $ret = array();
       
        if ($func == "" || !function_exists($func)) $func = "";       
       
        $len = strlen($str);
        $qtr = "";

        for ($i = 0; $i             $char = $str[$i];

            if (ord($char)                 // 读取到一个半角字符
                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);           
        }

        // return value
        if ($func == "") {
            return $ret;
        }
        else {
            return true;
        }
    }

    // 将句子切成词, 逆向
    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; // last freq
            for ($j = 1; $j _word_maxlen; $j++) {
                $o = $i - $j;
                if ($o                 $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 && $ord             return true;
        if (($ord >= 97 && $ord = 65 && $ord             return true;
        return false;
    }
}


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

// 实例(如果没有输入就从 sample.txt中读取):
$wp = new ch_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本次分词耗时: $time seconds
\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


     

     



    성명
    본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

    핫 AI 도구

    Undresser.AI Undress

    Undresser.AI Undress

    사실적인 누드 사진을 만들기 위한 AI 기반 앱

    AI Clothes Remover

    AI Clothes Remover

    사진에서 옷을 제거하는 온라인 AI 도구입니다.

    Undress AI Tool

    Undress AI Tool

    무료로 이미지를 벗다

    Clothoff.io

    Clothoff.io

    AI 옷 제거제

    Video Face Swap

    Video Face Swap

    완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

    뜨거운 도구

    에디트플러스 중국어 크랙 버전

    에디트플러스 중국어 크랙 버전

    작은 크기, 구문 강조, 코드 프롬프트 기능을 지원하지 않음

    Atom Editor Mac 버전 다운로드

    Atom Editor Mac 버전 다운로드

    가장 인기 있는 오픈 소스 편집기

    MinGW - Windows용 미니멀리스트 GNU

    MinGW - Windows용 미니멀리스트 GNU

    이 프로젝트는 osdn.net/projects/mingw로 마이그레이션되는 중입니다. 계속해서 그곳에서 우리를 팔로우할 수 있습니다. MinGW: GCC(GNU Compiler Collection)의 기본 Windows 포트로, 기본 Windows 애플리케이션을 구축하기 위한 무료 배포 가능 가져오기 라이브러리 및 헤더 파일로 C99 기능을 지원하는 MSVC 런타임에 대한 확장이 포함되어 있습니다. 모든 MinGW 소프트웨어는 64비트 Windows 플랫폼에서 실행될 수 있습니다.

    드림위버 CS6

    드림위버 CS6

    시각적 웹 개발 도구

    SecList

    SecList

    SecLists는 최고의 보안 테스터의 동반자입니다. 보안 평가 시 자주 사용되는 다양한 유형의 목록을 한 곳에 모아 놓은 것입니다. SecLists는 보안 테스터에게 필요할 수 있는 모든 목록을 편리하게 제공하여 보안 테스트를 더욱 효율적이고 생산적으로 만드는 데 도움이 됩니다. 목록 유형에는 사용자 이름, 비밀번호, URL, 퍼징 페이로드, 민감한 데이터 패턴, 웹 셸 등이 포함됩니다. 테스터는 이 저장소를 새로운 테스트 시스템으로 간단히 가져올 수 있으며 필요한 모든 유형의 목록에 액세스할 수 있습니다.