webAi.JpKw - ソースコード
説明
「Web AI」は、クロノス・クラウンの柳井政和が開発しているJavaScirptのライブラリです。「Web AI」を使うと、Web上からデータを取得して構築するWebページを、とても簡単に構築することができます。
「Web AI」は、Webからの検索結果やフィードの取得、短縮URLへのURLの変換、日本語文章からのキーワードや文章抽出、日本語文章のマルコフ連鎖、クエリーの管理などの機能を備えています。
このページでは、この「Web AI」のファイルの1つである「crocro.webAi.JpKw.js」のソースコードを掲載します。
「crocro.webAi.JpKw.js」
「crocro.webAi.JpKw.js」には、日本語の文字列から、キーワードとなりそうな文字列を抽出する機能がまとめられています。このファイルには「crocro.webAi.JpKw」オブジェクトが収録されています。
使い方は、「Web AI」の各サンプルを参考にしてください。
ソースコード
以下、「crocro.webAi.JpKw.js」のソースコードです。
// crocro.webAiの初期化
if (! crocro) var crocro = {};
if (! crocro.webAi) crocro.webAi = {};
/**
* @variable crocro.webAi.JpKw(arg)
* @title 日本語キーワード
* @description
*
* Webから取得した雑多な日本語から、キーワードを抽出するオブジェクト。
* newで初期化してから利用する。
*
* 引数は連想配列で設定する。例){~: "~", …}
*
* @param arg.avoidStr 無視文字列(,単語1,単語2,...,)
* @param arg.bsUrl 基準URL
* @param arg.outMax 描画キーワード最大数
* @param arg.kwLenMin キーワード文字数最小値
* @param arg.kwLenMid キーワード文字数中央値
*/
crocro.webAi.JpKw = function(arg) {
// ユーザー変数
/**
* @variable JpKw.avoidStr
* @title 無視文字列
* @description
* 無視文字列(単語1,単語2,...)。
*
* デフォルトは空文字。
*/
/**
* @variable JpKw.bsUrl
* @title 基準URL
* @description
* HTML化出力時の基準URL。
*
* デフォルトは「?q=」。
*/
/**
* @variable JpKw.outMax
* @title 描画キーワード最大数
* @description
* 出力時の最大キーワード数。
*
* デフォルトは「20」。
*/
this.avoidStr = ""; // 無視文字列(単語1,単語2,...)
this.bsUrl = "?q="; // 基準URL
this.outMax = 20; // 描画キーワード最大数
// キーワード抽出時の設定
/**
* @variable JpKw.kwLenMin
* @title キーワード文字数最小値
* @description
* キーワードとして認識する文字数の最小値。
*
* デフォルトは「2」。
*/
/**
* @variable JpKw.kwLenMid
* @title キーワード文字数中央値
* @description
* キーワードの標準的な文字長を規定する。
*
* デフォルトは「4」。
*/
this.kwLenMin = 2; // キーワード文字数最小値
this.kwLenMid = 4; // キーワード文字数中央値
// ユーザー変数の設定
if (arg) {
if ("avoidStr" in arg) this.avoidStr = arg.avoidStr;
if ("bsUrl" in arg) this.bsUrl = arg.bsUrl;
if ("outMax" in arg) this.outMax = arg.outMax;
if ("kwLenMin" in arg) this.kwLenMin = arg.kwLenMin;
if ("kwLenMid" in arg) this.kwLenMid = arg.kwLenMid;
}
// 内部利用変数
this.srcStr = ""; // キーワード収集対象文字列
// 配列位置変数
var CNT = 0; // 回数
var KW = 1; // キーワード
var PNT = 2; // 点数
// 無視文字列用点数
var AVOID_PNT = -999999;
/*
*--------------------------------------------------
*/
/**
* @variable JpKw.reset()
* @title リセット
* @description
*
* 内容をリセットしてメモリを解放する。
* 設定はそのまま維持する。
*
* @return なし
*/
this.reset = function() {
this.srcStr = "";
};
/**
* @variable JpKw.addSrc(str)
* @title 入力文字列の追加
* @description
*
* キーワード抽出用の入力文字列を追加する。
* 文字列は半角スペースで連結する。
*
* @param str 追加する文字列。
* @return なし
*/
this.addSrc = function(str) {
this.srcStr += " " + str;
};
/**
* @variable JpKw.getKwArr()
* @title キーワード配列の取得
* @description
*
* 入力した文字列を元に、キーワード配列を作成する。
*
* @return キーワード配列
*/
this.getKwArr = function() {
return this.getKeyWord(this.srcStr);
};
/**
* @variable JpKw.getStrArr(arg)
* @title キーワード配列を文字列配列に変換して取得
* @description
*
* 入力した文字列を元に、キーワード配列を作成する。
*
* @param arg.prmAll 値を全て戻すか。falseなら文字列のみを戻す。
* デフォルトはfalse。
* @return 文字列配列
*/
this.getStrArr = function(arg) {
// 引数の展開
var prmAll = false;
if (arg) {
if ("prmAll" in arg) prmAll = arg.prmAll;
}
// 配列の取得
var kwArr = this.getKeyWord(this.srcStr);
var resArr = this.kwArrToStrArr(kwArr, prmAll);
return resArr;
};
/**
* @variable JpKw.kwArrToStrArr(kwArr, prmAll)
* @title キーワード配列を文字列配列に変換
* @description
*
* 入力した文字列を元に、キーワード配列を作成する。
*
* @param kwArr キーワード配列。
* @param prmAll 値を全て戻すか(trueかfalse)。falseなら文字列のみを戻す。
* @return 文字列配列
*/
this.kwArrToStrArr = function(kwArr, prmAll) {
var strArr = [];
if (! kwArr || !(kwArr instanceof Array)) return strArr;
for (var i = 0; i < kwArr.length; i ++) {
if (! prmAll) {
strArr.push(kwArr[i][KW]);
} else {
strArr.push(kwArr[i].join("/"));
}
}
return strArr;
}
/*
*--------------------------------------------------
*/
/**
* @variable JpKw.outKw(eleId, arg)
* @title キーワードの出力
* @description
*
* 指定エレメントIDに、キーワードのリストを出力する。
*
* @param eleId エレメントIDを指定。
* @param arg.clsNm クラス名。
* @param arg.wrpFnc 要素の装飾用関数。
* @return なし
*/
this.outKw = function(eleId, arg) {
// 変数の初期化
var kwArr = this.getKwArr();
var kwLst = "";
// キーワードリストの作成
if (kwArr && kwArr.length > 0) {
for (var i = 0; i < kwArr.length && i < this.outMax; i ++) {
// 事前処理
kwArr[i][KW] = kwArr[i][KW].replace(/["<>]/g, ""); // 無効文字列の削除
if (kwArr[i][KW].indexOf("-") == 0) continue; // 無視文字列
if (kwArr[i][KW].length < this.kwLenMin) continue; // 描画キーワード文字最小数
// 文字列リスト作成
kwLst += this.makeLink(kwArr[i], arg) + "\n";
}
}
// キーワード・リストの出力
var outStr = '<DIV class="kwOut">' + kwLst + '</DIV>';
document.getElementById(eleId).innerHTML = outStr;
};
/**
* @variable JpKw.makeLink(kwObj, arg)
* @title リンク文字列の作成
* @description
*
* キーワードから、リンク文字列を作成する。
*
* @param kwObj キーワード
* @return リンクのHTML文字列
*/
this.makeLink = function(kwObj, arg) {
var clsNm = "";
var wrpFnc = null;
if (arg) {
if ("clsNm" in arg) clsNm = arg.clsNm;
if ("wrpFnc" in arg && arg.wrpFnc instanceof Function) wrpFnc = arg.wrpFnc;
}
var lnkStr = "";
lnkStr += '<a href="' + this.bsUrl + encodeURIComponent(kwObj[KW]) + '"';
lnkStr += ' title="評価ポイント ' + kwObj[PNT] + '" ';
lnkStr += ' class="' + clsNm + '"';
lnkStr += '>' + kwObj[KW] + "</a>";
if (wrpFnc != null) {
lnkStr = wrpFnc(lnkStr);
}
return lnkStr;
};
/*
*--------------------------------------------------
*/
/**
* @variable JpKw.getKeyWord(srcStr)
* @title キーワードの取得
* @description
*
* 日本語文字列から、キーワードを抽出する。
*
* @param srcStr 入力文字列。
* @return なし
*/
this.getKeyWord = function(srcStr) {
// 変数の初期化
var tmpArr;
var wrdArr = new Array();
var resArr = null;
var resArrSz = 0;
// 片仮名のみ2個以上か、漢字のみか、アルファベットと数字のみ2個以上か
var re = new RegExp( "[ァ-ヶ・=ー0-90-9一-龠々A-Za-z0-9\w\-]{2,}|[一-龠々]+", "ig" );
/*
*--------------------------------------------------
*/
// 評価ポイント計算用変数の初期化
// 漢字ブロック検出
var chkKnPrm = 1; var chkKnArr; var chkKnRe = new RegExp( "[一-龠々]{1,}", "ig" );
// 片仮名文字数
var chkKtPrm = 0; var chkKtArr; var chkKtRe = new RegExp( "[ァ-ヶ・=ー]{1,1}", "ig" );
// 数字
var chkNoPrm = 0; var chkNoArr; var chkNoRe = new RegExp( "[0-90-9]{1,}", "ig" );
// 英文字
var chkEnPrm = 0; var chkEnArr; var chkEnRe = new RegExp( "[A-Za-zA-Za-z]{1,}", "ig" );
// ドット
var chkDtPrm = 0; var chkDtArr; var chkDtRe = new RegExp( "・", "ig" );
/*
*--------------------------------------------------
*/
// 文字列の配列化
tmpArr = srcStr.match(re);
if (! tmpArr) {return resArr;}
for (var i = 1; i < tmpArr.length; i ++) {
if (tmpArr[i].length <= this.kwLenMin) continue;
wrdArr.push(tmpArr[i]);
}
if (wrdArr.length > 0) {
resArr = new Array(0); // 0 - 回数、1 - キーワード、2 - 点数
wrdArr = wrdArr.sort();
resArr[0] = new Array(2);
resArr[0][CNT] = 1;
resArr[0][KW] = wrdArr[0];
resArrSz ++;
for (var i = 1; i < wrdArr.length; i ++) {
if (wrdArr[i] == resArr[resArrSz - 1][KW]) {
// 一致
resArr[resArrSz - 1][CNT] ++;
} else {
// 不一致
resArr[resArrSz] = new Array(2);
resArr[resArrSz][CNT] = 1;
resArr[resArrSz][KW] = wrdArr[i];
resArrSz ++;
}
}
// 評価ポイント順にソート
for (var i = 0; i < resArrSz; i ++) {
// 漢字ブロック検出
chkKnPrm = 1; chkKnArr = resArr[i][KW].match(chkKnRe);
if (chkKnArr && chkKnArr.length > 0 && chkKnArr[0].length != resArr[i][1].length) {
chkKnPrm = 4;
}
// 片仮名文字数
chkKtPrm = 0; chkKtArr = resArr[i][KW].match(chkKtRe);
if (chkKtArr && chkKtArr.length > 0) {
chkKtPrm = chkKtArr.length;
}
// 数字
chkNoPrm = 0; chkNoArr = resArr[i][KW].match(chkNoRe);
if (chkNoArr && chkNoArr.length > 0) {
chkNoPrm = chkNoArr[0].length;
}
// 英文字
chkEnPrm = 0; chkEnArr = resArr[i][KW].match(chkEnRe);
if (chkEnArr && chkEnArr.length > 0) {
chkEnPrm = chkEnArr[0].length;
}
// ドット
chkDtPrm = 0; chkDtArr = resArr[i][KW].match(chkDtRe);
if (chkDtArr && chkDtArr.length > 0) {
chkDtPrm = chkDtArr[0].length;
}
// 評価ポイント計算
resArr[i][PNT] = Math.ceil(
resArr[i][CNT] * 0.5 // 個数 = 0.5point
* 10 / (1 + Math.abs(resArr[i][KW].length - this.kwLenMid)) // 文字数 - 中央値
- chkKtPrm * 0.5 // 片仮名一文字 = -0.5point
- chkNoPrm * 50 // 数字 = -50point
- chkEnPrm * 50 // 英文字 = -50point
- chkDtPrm * 50 // ドット = -50point
);
resArr[i][PNT] = resArr[i][PNT] * chkKnPrm; // 漢字を含む複合語 = 4.0倍
var re = new RegExp("," + resArr[i][1] + ",", "i");
if (("," + this.avoidStr + ",").match(re)) resArr[i][PNT] = AVOID_PNT; // 無視文字列
}
// 無視の配列は除く
var tmpArr = []
for (var i = 0; i < resArr.length; i ++) {
if (resArr[i][PNT] != AVOID_PNT) {
tmpArr.push(resArr[i]);
}
}
resArr = tmpArr;
// 結果をポイント順でソート
resArr = resArr.sort(this.srtKwPnt);
}
// 終了処理
return resArr;
};
/**
* @variable JpKw.srtKwPnt(a, b)
* @title ソート(評価ポイント順)
* @description
*
* キーワード配列を、評価ポイント順に並べ替えるためのソート用の比較子。
*/
this.srtKwPnt = function(a, b) {
// 同じポイント数ならソート(長い順と同じ)
if (b[PNT] == a[PNT]) {
// 同じ長さなら数の多さで判定
if (b[KW].length == a[KW].length) return (b[CNT] - a[CNT]);
if (b[CNT] == a[CNT]) return (b[KW].length - a[KW].length);
// 文字列長で判定
return (b[KW].length - a[KW].length);
}
// ポイント数で判定
return (b[PNT] - a[PNT]);
}
};







