需求很简单,解决很粗暴。
把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; }