2025
12
20
2010
12
08
抽出キーワードをタグクラウド風に表示。
最近、よくタグクラウドを見かけます。ただ目に映るというだけで、空に浮かぶ雲と同じで、あまり気にしたことはありません。けれども、面白いことは面白い。あらためてよく見てみると、なかなかよくできています。それぞれに若干違いがありますが、だいたい次のような特徴があります。
・重要度(頻出度)は、文字の大きさや色で表現される。
・順番はアルファベット順が多い。
アルファベットと利用度の両方でタグを検索できる仕掛けというわけです。
今回は、このタグクラウドに触発されて、文章中からキーワードを抽出して、それらのキーワードをタグクラウド的に表現する JavaScript に挑戦してみました。ただキーワードの順番は、出現回数優先としました。日本語をあいうえお順で並べ替えるのは困難だと思ったからです。
キーワードの抽出
まず、どのようにキーワードを抽出するかが問題となります。これについては、最初、Yahoo! Japan デベロッパーネットワークのテキスト解析:キーワード抽出API の利用を考えました。しかしながら、利用回数の制限(アプリケーションIDあたり24時間に5万回)があるため、今回は見送ることにしました。零細サイトでは十分な回数ですが、今、大量にキーワードを抽出するアプリケーションを開発中なので、そこでは利用できないと判断したのです。
そこで思いついたのが、漢字とカタカナだけに割り切るという方法です。日本語なら、これで相当いい線いけるでしょう。しかも、実装が容易です。正規表現で半角英数字や記号やひらがなを区切り文字に変換してしまえばよいのです。そして、その区切り文字で配列化し、各文字列の出現回数を調べるのです。
重要度の表現方法
各文字列の重要度は、その出現回数とします。データベースやAPIを利用しない限り、他に方法はないでしょう。そして、その重要度は、表示順序に加え、文字の大きさと色合いの両方で表現します。なお、同じ出現回数のものは、文字数の多い方を先に表示することにしました。場合によっては、1文字のものは表示対象から外してもよいかもしれません。
文字サイズは、表示領域の幅と高さを把握した上で全体の文字数から割り出します。
文字色は、カラーコードの配列を用意しておき、出現回数によってどれを適用するか決定することにしました。自動的に色調を計算させる案もありますが、今回は関数を探す時間がなかったので諦めました。
コード
(function(){
neta.stringCloud=function(container,text,size){
//variables
var colorWeight
=['#99ccff',"#6699cc",'#336699','#003366'];
var r_keywords
=/([ぁ-ゞ、。ヲ-゚\w\s\t。-゚「」,:/.(),.+;()@])/g;
var a=[];
var b=[];
//parse
var v=text.replace(r_keywords,'|');
a=v.split('|');
for(var i=0;i<a.length;i++){
if(!a[i])continue;
var flg=false;
for(j=0;j<b.length;j++){
if(b[j][0]==a[i]){
b[j][1]++;
flg=true;
break;
}
}
//except null
if(!flg)b.push([a[i],1]);
}
for(var i=0,total=0;i<b.length;i++){
var len=b[i][0].length;
b[i][2]=len;
total+=len*b[i][1];
}
b.sort(function(a,b){return b[2]-a[2]});
b.sort(function(a,b){return b[1]-a[1]});
//rendar
size=size||150;
var cloud=document.createElement('div');
cloud.style.textAlign='center';
cloud.style.width=size+'px';
cloud.style.height=size+'px';
cloud.style.padding='4px';
cloud.style.overflow='show';
container.innerHTML='';
container.appendChild(cloud);
var csize
=Math.floor(Math.sqrt(size*size/total))/1.5-2;
for(var i=0;i<b.length;i++){
var div=document.createElement('div');
div.innerHTML=b[i][0];
div.style.position='static';
div.style.fontSize=(csize*b[i][1])+'px';
div.style.width=(csize*b[i][1]*b[i][2])+'px';
div.style.display='inline';
div.style.float='left';
div.style.margin='0 4px';
div.style.color
=colorWeight[b[i][1]<4?b[i][1]-1:3];
div.style.whiteSpace='nowrap';
cloud.appendChild(div);
}
var hr=document.createElement('hr');
hr.style.margin=0;
hr.style.border=0;
hr.style.clear='both';
cloud.appendChild(hr);
}
neta.addListener(function(){
var container=document.getElementById('t20101208');
var text=document.getElementById('text20101208');
var btnExtract=document.getElementById('btn20101208');
neta.stringCloud(container,text.value,200);
btnExtract.onclick=function(){
neta.stringCloud(container,text.value,200);
}
});
2010/12/08 (Wed.) Trackback() Comment(0) JavaScript
Comments
Trackback
Trackback for this entry:
