有示例,利用数据库已有的词库(20万条左右)提取文章标题的关键词,求解

kiqigai 2011-08-13 07:06:52
已有词库:

数据表如下:

id keyword
125 豹纹
126 坡跟
.
2562 单鞋
.
56895 欧美
.

词库共计23万条关键词!

求php 怎样能把一个文章的标题中与词库匹配的关键词提取出来,并排列成数组

如下标题:

庆皇冠 特价 欧美JC同款绒面防水台坡跟女鞋 豹纹女单鞋

把此标题中的关键词提取排列为:

欧美,坡跟,豹纹,单鞋

有示例代码,但是词库是保存在文件里面的,若果用文件保存词库二十多万估计文件会很大,所以想用数据库
求高人了,搞个高效快速提取关键词的东东出来~~估计除了俺 还有很多人需要哈 ~~~多谢了先~

示例代码:


<?
//RMM分词算法
class SplitWord{
var $TagDic = Array();
var $RankDic = Array();
var $SourceStr = '';
var $ResultStr = '';
var $SplitChar = ' '; //分隔符
var $SplitLen = 4; //保留词长度
var $MaxLen = 7; //词典最大中文字,这里的数值为字节数组的最大索引
var $MinLen = 3; //最小中文字,这里的数值为字节数组的最大索引

function SplitWord(){
$this->__construct();
}

function __construct(){
//高级分词,预先载入词典以提分词高速度
$dicfile = dirname(__FILE__)."/ppldic.csv";
$fp = fopen($dicfile,'r'); //读取词库中的词
while($line = fgets($fp,256)){
$ws = explode(' ',$line); //对词库中的词进行拆分
$this->TagDic[$ws[0]] = $ws[1];
$this->RankDic[strlen($ws[0])][$ws[0]] = $ws[2];
}
fclose($fp); //关闭词库文件
}

//析放资源
function Clear(){
@fclose($this->QuickDic);
}

//设置源字符串
function SetSource($str){
$this->SourceStr = $this->UpdateStr($str);
$this->ResultStr = "";
}

//检查字符串是否不存在中文
function NotGBK($str)
{
if($str=="") return "";
if( ord($str[0])>0x80 ) return false;
else return true;
}

//RMM分词算法
function SplitRMM($str=""){
if($str!="") $this->SetSource($str);
if($this->SourceStr=="") return "";
$this->SourceStr = $this->UpdateStr($this->SourceStr);
$spwords = explode(" ",$this->SourceStr);
$spLen = count($spwords);
$spc = $this->SplitChar;
for($i=($spLen-1);$i>=0;$i--){
if($spwords[$i]=="") continue;
if($this->NotGBK($spwords[$i])){
if(ereg("[^0-9\.\+\-]",$spwords[$i]))
{ $this->ResultStr = $spwords[$i].$spc.$this->ResultStr; }
else
{
$nextword = "";
@$nextword = substr($this->ResultStr,0,strpos($this->ResultStr,""));
}
}
else
{
$c = $spwords[$i][0].$spwords[$i][1];
$n = hexdec(bin2hex($c));
if(strlen($spwords[$i]) <= $this->SplitLen)
{
}
else
{
$this->ResultStr = $this->RunRMM($spwords[$i]).$spc.$this->ResultStr;
}
}
}
return $this->ResultStr;
}
//对全中文字符串进行逆向匹配方式分解
function RunRMM($str){
$spc = $this->SplitChar;
$spLen = strlen($str);
$rsStr = "";
$okWord = "";
$tmpWord = "";
$WordArray = Array();
//逆向字典匹配
for($i=($spLen-1);$i>=0;){
//当i达到最小可能词的时候
if($i<=$this->MinLen){
if($i==1){
$WordArray[] = substr($str,0,2);
}else
{
$w = substr($str,0,$this->MinLen+1);
if($this->IsWord($w)){
$WordArray[] = $w;
}else{
$WordArray[] = substr($str,2,2);
$WordArray[] = substr($str,0,2);
}
}
$i = -1; break;
}
//分析在最小词以上时的情况
if($i>=$this->MaxLen) $maxPos = $this->MaxLen;
else $maxPos = $i;
$isMatch = false;
for($j=$maxPos;$j>=0;$j=$j-2){
$w = substr($str,$i-$j,$j+1);
if($this->IsWord($w)){
$WordArray[] = $w;
$i = $i-$j-1;
$isMatch = true;
break;
}
}
}
$rsStr = $this->otherword($WordArray);
return $rsStr;
}

function otherword($WordArray){
$wlen = count($WordArray)-1; //计算数组的元素个数
$rsStr = ""; //初始化变量
$spc = $this->SplitChar;
for($i=$wlen;$i>=0;$i--)
{
$rsStr .= $spc.$WordArray[$i]."、"; //将数组为顿号进行拆分
}
//返回本段分词结果
$rsStr = preg_replace("/^".$spc."/","、",$rsStr);
return $rsStr;
}

//判断词典里是否存在某个词
function IsWord($okWord){
$slen = strlen($okWord);
if($slen > $this->MaxLen) return false;
else return isset($this->RankDic[$slen][$okWord]);
}

//整理字符串(对标点符号,中英文混排等初步处理)
function UpdateStr($str){
$spc = $this->SplitChar;
$slen = strlen($str);
if($slen==0) return '';
$okstr = '';
$prechar = 0; // 0-空白 1-英文 2-中文 3-符号
for($i=0;$i<$slen;$i++){
if(ord($str[$i]) < 0x81){
//英文的空白符号
if(ord($str[$i]) < 33){
if($prechar!=0&&$str[$i]!="\r"&&$str[$i]!="\n") $okstr .= $spc;
$prechar=0;
continue;
}else if(ereg("[^0-9a-zA-Z@\.%#:/\\&_-]",$str[$i])){
if($prechar==0){ $okstr .= $str[$i]; $prechar=3;}
else{ $okstr .= $spc.$str[$i]; $prechar=3;}
}else{
if($prechar==2||$prechar==3)
{ $okstr .= $spc.$str[$i]; $prechar=1;}
else
{
if(ereg("@#%:",$str[$i])){ $okstr .= $str[$i]; $prechar=3; }
else { $okstr .= $str[$i]; $prechar=1; }
}
}
}
else{
//如果上一个字符为非中文和非空格,则加一个空格
if($prechar!=0 && $prechar!=2) $okstr .= $spc;
//如果中文字符
if(isset($str[$i+1])){
$c = $str[$i].$str[$i+1];

$n = hexdec(bin2hex($c));
if($n<0xA13F && $n > 0xAA40){
if($prechar!=0) $okstr .= $spc.$c;
else $okstr .= $c;
$prechar = 3;
}
else{
$okstr .= $c;
$prechar = 2;
}
$i++;
}
}
}
return $okstr;
}
}
?>



将这个类保存到文件“splitword.php”
类的方法已经添加进去了,接下来就是使用这个方法。
首先要实例化
require("splitword.php");//包含分词类文件
$sp=new SplitWord();//创建类对象
$str="某某字符串";
$sp->SplitRMM($str);//调用类方法
...全文
595 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
by53008749 2011-08-15
  • 打赏
  • 举报
回复
关注下。
码无边 2011-08-15
  • 打赏
  • 举报
回复
function   CsubStr($str,   $start=0,   $length=20,   $suffix= '... ',   $charset= "utf-8 ")
{

if(@function_exists( "mb_substr "))
{
$slice = @mb_substr($str, $start, $length, $charset);
if( mb_strlen($str,$charset) > $start+$length )$slice.=$suffix;
Return $slice;
}

$re[ 'utf-8 '] = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/ ";
//简化后为
//$re[ 'utf-8 '] = "/[\x00-\x7f]|[\xc0-\xff][\x80-\xbf]+/ ";
$re[ 'gb2312 '] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/ ";
$re[ 'gbk '] = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/ ";
$re[ 'big5 '] = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/ ";

preg_match_all($re[$charset], $str, $match);
$slice = @join( " ",array_slice($match[0], $start, $length));

if( strlen($str) > $start+$length )$slice.=$suffix;

Return $slice;
}//End Function
zhou1ting1ting1 2011-08-15
  • 打赏
  • 举报
回复
用树对词典进行存储,查询的时候从顶点开始查找是否满足。
php600 2011-08-13
  • 打赏
  • 举报
回复
留名.....

21,886

社区成员

发帖
与我相关
我的任务
社区描述
从PHP安装配置,PHP入门,PHP基础到PHP应用
社区管理员
  • 基础编程社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧