需求很简单,解决很粗暴。
把wordnet db file导入到mysql数据库中
文件分为两种,
index.* 索引文件 除了index.sense
data.* 数据文件
所以,表也就两个。
但是,wordnet有*.exc文件,也就是单词的变形。在我这,这个需求被砍了。。。被砍的还有上下位词啊什么语义语素方面的东西,那些单词没有中文解释。。不过,sql表结构还是遵从源文件的数据格式的,所以数据没有缺失。
嗯,只关注了这两种文件,所以那些语义语素之类的暂时抛弃了。
读文件,按空格切成数组,读字段,生成sql插入语句,执行插入。
因为需要大量插入,所以,调大了max_allowed_packet,表使用InnoDB引擎。插入效率棒棒哒。
这只是整理数据,具体的界面还没有放到github上。
上代码,TL;DR
function index($line)
{
global $sql;
$one=explode(' ',$line);//空格作为分隔符
$lemma = $sql->escape_string($one[0]);//转义lemma,有些单词包含单引号
$pos = $one[1];
$synset_cnt = $one[2];
$ptr_cnt = $one[3]*1;//指针个数为十进制,*1转为int类型
$ptr = '';
if($ptr_cnt!=0){
for($i=0;$i<$ptr_cnt;$i++){
$ptr .= '"'.$one[$i+4].'",';
}
}
$ptr = $ptr!=''?$sql->escape_string('['.trim($ptr,',').']'):null;
$sense_cnt = $one[$ptr_cnt+4]*1;
$tagsense_cnt = $one[$ptr_cnt+5]*1;
$offset = '';
for($i=0;$i<$synset_cnt;$i++){
$offset .='"'.$one[$i+6+$ptr_cnt].'",';
}
$offset = '['.trim($offset,',').']';
$value = "('$lemma','$pos','$synset_cnt','$ptr_cnt','$ptr','$sense_cnt','$tagsense_cnt','$offset'),";
return $value;
}
function data($line)
{
global $sql;
$one = explode('|',$line); //先以 | 作为分隔符分开大部分字段和gloss字段,分别单独处理
$data = explode(' ',$one[0]); //再以空格分开
$offset = $data[0];
$lex_filenum = $data[1]*1;
$ss_type = $data[2];
$w_cnt = hexdec($data[3]);
$word_max = $w_cnt*2+3;// $w_cnt*2-1+4
$word = array_slice($data,4,$w_cnt*2);
$word = array_chunk($word,2);
/* just get word , remove lex_id 这段注释里的代码只获取单词,不获取分词id
$countWord = count($word);$w='';
for($i=0;$i<=$countWord;$i+=2){
if($i==$countWord)
break;
$w[]=$word[$i];
}
*/
$word = $sql->escape_string(json_encode($word));
$p_cnt = $data[$word_max+1]*1;
$ptr="";
if($p_cnt!=0){
$ptr = array_slice($data,$word_max+2,$p_cnt*4);
$ptr = array_chunk($ptr,4);
$ptr = json_encode($ptr);
}
$frames = "";
$f_cnt = 1*$data[$w_cnt*2+$p_cnt*4+5]; //$w_cnt*2+4+$p_cnt*4+1
if($f_cnt!=0){
$frame = array_slice($data,$w_cnt*2+$p_cnt*4+6,$f_cnt*3);
$countFrame = count($frame);
for($i=0;$i<$countFrame;$i+=3){
$frames[]=($i<$countFrame)?array_merge([$frame[$i+1]],[$frame[$i+2]]):'';
}
$frames = json_encode($frames);
}
$gloss = explode(';',trim($one[1])); //gloss分为单词定义和例句,用分号分隔。目前3.1有些单词包含了冒号,应该是打错了。。有些用冒号代替了分号,这绝对是打错了。。
$definition = '';
$sentence = '';
$countGloss = count($gloss);
for($j=0;$j<$countGloss;$j++){
$gloss[$j] = trim($gloss[$j]);
/* a little bug; so ...有些单词定义包含了双引号,所以这段注释了
if(preg_match('#^[\"]#',trim($gloss[$j]))){
$sentence[]=$gloss[$j];
}else{
$definition=$gloss[$j];
}
*/
//$j==0?$definition=$gloss[$j]:$sentence[]=$gloss[$j]; //a little bug too.. like offset='09560255' 有些单词定义不止一个,所以,这个也注释了
preg_match('#^"(.*)"$#', $gloss[$j])?$sentence[]=$gloss[$j]:$definition[]=$gloss[$j];
}
$definition = $sql->escape_string(json_encode($definition));
$sentence = $sentence==""?null:$sql->escape_string(json_encode($sentence));
$value = "('$offset', $lex_filenum, '$ss_type', $w_cnt, '$word', $p_cnt, '$ptr', $f_cnt, '$frames', '$definition','$sentence'),";
return $value;
}