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]); } };