迷言辞典 - ソースコード

説明

迷言辞典」は、「Web AI」を使ったWebアプリです。このページでは、この「迷言辞典」を作るために書いたプログラムを掲載します。

「Web AI」は、クロノス・クラウンの柳井政和が開発しているJavaScirptのライブラリです。「Web AI」を使うと、Web上からデータを取得して構築するWebページを、とても簡単に構築することができます。

「Web AI」は、Webからの検索結果やフィードの取得、短縮URLへのURLの変換、日本語文章からのキーワードや文章抽出、日本語文章のマルコフ連鎖、クエリーの管理などの機能を備えています。

コアとなる「WebSrch」オブジェクトでは、非同期で行われる通信処理に対して、その結果を待ちながら順番に処理していくプログラムを簡単に書くことができます。また、本ライブラリでは「Google AJAX Search API」を抽象化して、検索データを手軽にプログラムに読み込んで利用できるようにしています。

「迷言辞典」は、この「Web AI」のサンプルとして作成しました。このWebアプリを作成したソースコードを見れば、その簡単さがよく分かると思います。それでは以下に、ソースコードを掲載します。

ソースコード

まずは、HTMLのヘッダー部分のソースコードです。

  1. <!-- Google API -->
  2. <script src="http://www.google.com/jsapi" type="text/javascript"></script>
  3.  
  4. <!-- Web AI API -->
  5. <script src="crocro.webAi.min.js" type="text/javascript" charset="UTF-8"></script>
  6.  
  7. <!-- ScriptThis -->
  8. <script src="app.js" type="text/javascript" charset="UTF-8"></script>

次に、Webアプリ本体部分になる「app.js」のソースコードを掲載します。

  1. /**
  2. * 【変数の初期化】
  3. */
  4. // Googleからスクリプトをロード
  5. google.load("search", "1");
  6. google.load("feeds", "1");
  7. google.load("jquery", "1.4.3");
  8.  
  9. // Web AIの初期化
  10. var $WA = crocro.webAi; // 短縮表記
  11. var cQ = new $WA.Query(); // クエリー
  12. var cWSrch = new $WA.WebSrch(); // Web検索用
  13. var cISrch = new $WA.WebSrch(); // 画像検索用
  14. var cJpKw = new $WA.JpKw(); // キーワード
  15. var cJpSntnc = new $WA.JpSntnc(); // センテンス
  16.  
  17. var qKeyQckSrch = "qckSrch"; // 急速検索
  18.  
  19. var loadAnmArr // ロード中アニメ配列
  20. = [".(^o^).", "(^o^)..", "^o^)..(", "o^)..(^", "^)..(^o", ")..(^o^", "..(^o^)"];
  21. var loadAnmCnt = 0; // ロード中アニメ・カウンター
  22.  
  23. var appNm = "迷言辞典";
  24.  
  25. /*
  26. *--------------------------------------------------
  27. */
  28.  
  29. /**
  30. * 【初期化処理】
  31. */
  32. cWSrch.ready(function(){
  33. // デフォルトの固定URLを作成
  34. $("#fix_url_raw").val(getUrlBs());
  35. $("#fix_url_min").val(getUrlBs());
  36. setSclUrl(getUrlBs()); // ソーシャル系URL設定
  37. setTimeout(loadDelay, 1000); // 遅延読み込み
  38.  
  39. // クエリーの初期化
  40. cQ.prsFrmLocation({useH: true});
  41.  
  42. // 検索結果出力先の追加
  43. var deco = function(r) {
  44. if ("unescapedUrl" in r) return r.unescapedUrl + "\n";
  45. return "";
  46. }
  47. cISrch.appndResTgt = "vwSrchRes";
  48. cWSrch.appndResTgt = "vwSrchRes";
  49. cISrch.appndResDeco = deco;
  50. cWSrch.appndResDeco = deco;
  51.  
  52. // 画像検索用WebSrchを初期化
  53. cISrch
  54. .init({
  55. type : "img",
  56. opt : function(obj) {
  57. obj.setRestriction(google.search.ImageSearch.RESTRICT_IMAGETYPE,
  58. google.search.ImageSearch.IMAGETYPE_PHOTO); // 写真
  59. }
  60. })
  61. .start();
  62.  
  63. // Web検索用WebSrchを初期化
  64. cWSrch
  65. .brand("gglBrnd")
  66. .init({
  67. type : "web",
  68. opt : function(obj) {
  69. obj.setResultSetSize(google.search.Search.LARGE_RESULTSET); // 8件
  70. }
  71. })
  72. .init({
  73. type : "nws",
  74. opt : function(obj) {
  75. obj.setResultSetSize(google.search.Search.LARGE_RESULTSET); // 8件
  76. }
  77. })
  78. .feed({
  79. // 最新ニュースのキーワードリストを取得
  80. url : "http://www.google.co.jp/trends/hottrends/atom/hourly",
  81. res : function(res) {
  82. // エラー確認
  83. if (res.error) return; // エラーなので終了
  84.  
  85. // キーワードの取得
  86. var contentStr = res.feed.entries[0].content;
  87. var getArr = contentStr.match(/>[^\w\n]+?</g);
  88. if (! getArr instanceof Array) return; // エラーなので終了
  89. getArr = $.map(getArr, function(n, i){
  90. return n.replace(/[<>]/g, "");
  91. });
  92.  
  93. // HTMLの作成
  94. for (var i = 0; i < getArr.length; i ++) {
  95. // URL作成
  96. var urlStr = ""
  97. + ($WA.Tools.isLocal() ? "#" : "?") // ローカルの場合は#
  98. + qKeyQckSrch + "=" + encodeURIComponent(getArr[i]);
  99.  
  100. // HTML作成
  101. var htmlStr = '<span class="newItm">'
  102. + '<a href="' + urlStr + '">'
  103. + getArr[i]
  104. + '</a>'
  105. + '</span>';
  106.  
  107. getArr[i] = htmlStr
  108. }
  109.  
  110. // HTMLの挿入
  111. $("#newLst").html(getArr.join(" "));
  112. }
  113. });
  114.  
  115. if (cQ.get(qKeyQckSrch) != "") {
  116. // 急速検索がある場合は、検索処理を追加
  117. cWSrch
  118. .add(function() {
  119. $("#q").val(cQ.get(qKeyQckSrch)); // キーワードを設定
  120. strtSrch(); // 検索開始
  121. });
  122. } else
  123. if (cQ.get("kw") != ""
  124. && cQ.get("nms") != ""
  125. && cQ.get("bdy") != ""
  126. ) {
  127. cWSrch
  128. .add(function() {
  129. // 復帰用のデータがあるので画面を復帰
  130. $("#resVw").html(qry2Html(cQ)); // クエリーをHTMLに
  131. kw2Img(); // 画像の挿入
  132.  
  133. // 固定URLを作成
  134. var urlStr = getUrlBs(); // URL基本部分取得
  135. urlStr += "?" + cQ.getCmprsQuery(); // 圧縮をかけたクエリーを取得
  136. $("#fix_url_raw").val(urlStr);
  137. setSclUrl(urlStr); // ソーシャル系URL設定
  138. });
  139. }
  140.  
  141. cWSrch
  142. .setEachCall(function(){
  143. // ステップごとに呼び出される処理を追加
  144. drwLoadAnm(true); // ロードアニメ描画
  145. })
  146. .start();
  147. });
  148.  
  149. /*
  150. *--------------------------------------------------
  151. */
  152.  
  153. /**
  154. * @title 【検索開始】
  155. * @description
  156. *
  157. * 検索を実行する。ボタンから呼び出す。
  158. */
  159. function strtSrchBtn() {
  160. // 実行中回避処理
  161. if (cWSrch.isExec) {
  162. alert("現在、検索中です。\n\n少々お待ち下さい。");
  163. return;
  164. }
  165.  
  166. // 検索実行
  167. cWSrch.reset();
  168. strtSrch();
  169. cWSrch.start();
  170. }
  171. function strtSrch() {
  172. // 変数の初期化
  173. var kwStrt = $("#q").val(); // 開始キーワード
  174. var kwGetArr = []; // 収集キーワード配列
  175. var nmGetArr = []; // 収集名前配列
  176. var cQRes = new $WA.Query(); // 結果クエリー
  177.  
  178. // 開始キーワードのトリム
  179. kwStrt = kwStrt.replace(/^[  ]+|[  ]$/g, "");
  180.  
  181. // オブジェクトの内容のリセット
  182. cJpKw.reset(); // 日本語キーワードオブジェクトの内容をリセット
  183. cJpSntnc.reset(); // 日本語文章オブジェクトの内容をリセット
  184.  
  185. // 検索処理
  186. cWSrch
  187. .srch({
  188. // ニュースを検索して、キーワードと文章を収集
  189. type : "nws",
  190. page : 8,
  191. key : kwStrt,
  192. res : function(res, cursor) {
  193. if (! res || res.length <= 0) return; // 結果なし
  194.  
  195. for (var i = 0; i < res.length; i ++) {
  196. var r = res[i];
  197. cJpKw.addSrc(r.titleNoFormatting); // キーワード用に文字列を追加
  198. cJpSntnc.addSntnc(r.content); // 文章用に文字列を追加
  199. }
  200. }
  201. })
  202. .srch({
  203. // Webを検索して、キーワードと文章を収集
  204. type : "web",
  205. key : kwStrt,
  206. page : 8,
  207. res : function(res, cursor) {
  208. if (! res || res.length <= 0) return; // 結果なし
  209.  
  210. for (var i = 0; i < res.length; i ++) {
  211. var r = res[i];
  212. cJpKw.addSrc(r.titleNoFormatting); // キーワード用に文字列を追加
  213. cJpSntnc.addSntnc(r.content); // 文章用に文字列を追加
  214. }
  215. }
  216. })
  217. .feed({
  218. url : function() {
  219. return "http://searchranking.yahoo.co.jp/rss/total_ranking-people-rss.xml";
  220. },
  221. res : function(res) {
  222. if (! res.error) {
  223. for (var i = 0; i < res.feed.entries.length; i++) {
  224. var e = res.feed.entries[i];
  225. nmGetArr.push(e.title);
  226. }
  227. }
  228. }
  229. })
  230. .add(function() {
  231. // 文章配列を取得
  232. var sArr = cJpSntnc.getSntncArr();
  233. var kwArr = cJpKw.getStrArr();
  234.  
  235. // マルコフ連鎖で文章を生成
  236. var cJpMrkv = new $WA.JpMrkv();
  237. cJpMrkv.setSntncArr(sArr);
  238. var mrkvSArr = [];
  239. for (var i = 0; i < 100; i ++) {
  240. var str = cJpMrkv.getSntnc({strtStr: kwStrt});
  241. if (str == "") continue;
  242. if ($.inArray(str, sArr) != -1) continue;
  243.  
  244. mrkvSArr.push(str);
  245. }
  246. mrkvSArr = $WA.Tools.unq(mrkvSArr); // ユニークに
  247.  
  248. mrkvSArr = cJpSntnc.sortLen(mrkvSArr, 25); // 25文字位置でソート
  249. nmGetArr = $WA.Tools.shffl(nmGetArr); // シャッフル
  250.  
  251. // 全て出力
  252. var outArr = cJpSntnc.sortLong(mrkvSArr).reverse();
  253. var outStr = "";
  254. for (var i = 0; i < outArr.length; i ++) {
  255. outStr += i + ". " + outArr[i] + "。<br><br>";
  256. }
  257. $("#mrkvLst").html(outStr);
  258.  
  259. // HTML用データをクエリーへ格納
  260. cQRes.set("kw", kwStrt);
  261. cQRes.set("nms", nmGetArr.slice(0, 6).join("\n"));
  262. cQRes.set("bdy", mrkvSArr.slice(0, 6).join("\n"));
  263.  
  264. // 記事を出力
  265. $("#resVw").html(qry2Html(cQRes)); // クエリーをHTMLに
  266.  
  267. cJpKw.avoidStr = kwStrt; // 無視文字列
  268. cJpKw.bsUrl = ($WA.Tools.isLocal() ? "#" : "?") + qKeyQckSrch + "=";
  269. cJpKw.outKw("kwLst", { // キーワードリスト挿入
  270. clsNm : "kwItm",
  271. wrpFnc : function(s) {return '<nobr>' + s + '</nobr>'}
  272. });
  273.  
  274. kw2Img(); // 画像の挿入
  275. })
  276. .add(function() {
  277. // 固定URLを作成
  278. var urlStr = getUrlBs(); // URL基本部分取得
  279. urlStr += "?" + cQRes.getCmprsQuery(); // 圧縮をかけたクエリーを取得
  280. $("#fix_url_raw").val(urlStr);
  281. setSclUrl(urlStr); // ソーシャル系URL設定
  282.  
  283. // 検索の終了
  284. drwLoadAnm(false); // ロードアニメ描画
  285. });
  286. }
  287.  
  288. /*
  289. *--------------------------------------------------
  290. */
  291.  
  292. /**
  293. * @title 【URL基本部分取得】
  294. * @description
  295. *
  296. * URLの本体を取得。
  297. *
  298. * @return URLの本体部分
  299. */
  300. function getUrlBs() {
  301. var urlStr = "http://www.google.com/"; // ダミー
  302. if (! $WA.Tools.isLocal()) {
  303. // ネット上なので、URLをそのまま利用
  304. urlStr = location.href.replace(/\?.*$|#.*$/g, ""); // 本体部分のみ取得
  305. }
  306. return urlStr;
  307. }
  308.  
  309. /**
  310. * @title 【クエリーからHTML作成】
  311. * @description
  312. *
  313. * クエリーを元にして、HTMLを作成する。
  314. *
  315. * @param q クエリー・オブジェクト
  316. * @return HTML文字列
  317. */
  318. function qry2Html(q) {
  319. // エラー対策
  320. if (q.get("kw") == "") return;
  321. if (q.get("nms") == "") return;
  322. if (q.get("bdy") == "") return;
  323.  
  324. // 変数の初期化
  325. var resStr = "";
  326. var nmArr = q.get("nms").split("\n");
  327. var bdyArr = q.get("bdy").split("\n");
  328.  
  329. // HTMLの作成
  330. resStr += wrpDiv("「" + q.get("kw") + "」についての有名人の迷言", "itm_hdr");
  331.  
  332. for (var i = 0; i < 4 && i < bdyArr.length; i ++) {
  333. if (i > 0) resStr += "<hr>";
  334. if (i < nmArr.length) { // 人間画像
  335. resStr += wrpDiv(
  336. wrpDiv(nmArr[i], "imgRep"),
  337. "itm_img"
  338. );
  339. }
  340.  
  341. resStr += wrpDiv(bdyArr[i] + "。", "itm_bdy");
  342. resStr += wrpDiv("by " + nmArr[i], "itm_nm");
  343.  
  344. var cQUnq = new $WA.Query(); // クエリ
  345. cQUnq.prsFrmUrl({url: getUrlBs()});
  346. cQUnq.set("kw", q.get("kw"));
  347. cQUnq.set("nms", nmArr[i]);
  348. cQUnq.set("bdy", bdyArr[i]);
  349.  
  350. var unqPgLnk = ''
  351. + '<a href="'
  352. + cQUnq.getCmprsUrl() + '" '
  353. + 'target="_blank">'
  354. + '個別ページを開く'
  355. + '</a>';
  356.  
  357. resStr += wrpDiv(unqPgLnk, "itm_lnk");
  358. }
  359.  
  360. resStr = wrpDiv(resStr, "itm_out");
  361. return resStr;
  362. }
  363.  
  364. function wrpDiv(inSTr, cls) {
  365. if (! cls) cls= "";
  366. var resStr = "";
  367. resStr += '<div class="' + cls + '">';
  368. resStr += inSTr;
  369. resStr += '</div>';
  370. return resStr;
  371. }
  372.  
  373. /**
  374. * @title 【ロードアニメ描画】
  375. * @description
  376. *
  377. * ロード中のアニメを描画する。
  378. *
  379. * @param loading ロード中か否か
  380. * @return なし
  381. */
  382. function drwLoadAnm(loading) {
  383. var dwStr = ""
  384. if (loading) {
  385. dwStr = "Now Loading... " + loadAnmArr[loadAnmCnt ++ % loadAnmArr.length];
  386. }
  387. $("#loading").text(dwStr);
  388. }
  389.  
  390. /**
  391. * @title 【ソーシャル系URL設定】
  392. * @description
  393. *
  394. * ソーシャル系のサービスのウィジットにURLを指定する。
  395. *
  396. * @param urlStr URL文字列
  397. * @return なし
  398. */
  399. function setSclUrl(urlStr) {
  400. // ローカル時は無効
  401. if ($WA.Tools.isLocal()) return;
  402.  
  403. // 引数を解析
  404. var cQSrc = new $WA.Query();
  405. cQSrc.prsFrmUrl({url: urlStr});
  406. var kw = cQSrc.get("kw");
  407. var bdyArr = cQSrc.get("bdy").split("\n");
  408. var nmArr = cQSrc.get("nms").split("\n");
  409.  
  410. // 変数の初期化
  411. var cQTmp;
  412. var urlTmp;
  413.  
  414. // AddClip ブックマーク用URL
  415. AddClipsUrl = urlStr;
  416.  
  417. // Twitter用URL
  418. cQTmp = new $WA.Query(); // クエリ解析用
  419. cQTmp.prsFrmUrl({url: $(".twitter-share-button").attr("src")});
  420. cQTmp.set("url", urlStr);
  421. if (bdyArr.length == 1) {
  422. cQTmp.set("text", appNm + " - " + bdyArr[0] + " by " + nmArr[0]);
  423. } else {
  424. cQTmp.set("text", appNm + " - 「" + kw + "」についての迷言");
  425. }
  426. $(".twitter-share-button").attr("src", cQTmp.getUrl());
  427.  
  428. // Facebookシェア用URL
  429. cQTmp = new $WA.Query(); // クエリ解析用
  430. cQTmp.prsFrmUrl({url: $("#fcbkShare").attr("href")});
  431. cQTmp.set("u", urlStr);
  432. $("#fcbkShare").attr("href", cQTmp.getUrl());
  433.  
  434. // Facebookいいね用URL
  435. cQTmp = new $WA.Query(); // クエリ解析用
  436. cQTmp.prsFrmUrl({url: $("#fcbkLike").attr("src")});
  437. cQTmp.set("href", urlStr);
  438. $("#fcbkLike").attr("src", cQTmp.getUrl());
  439.  
  440. // はてブ用URL
  441. var htbEntryAdd = "http://b.hatena.ne.jp/entry/add/" + urlStr;
  442. var htbEntryUrl = "http://b.hatena.ne.jp/entry/" + urlStr;
  443. var htbEntryImg = "http://b.hatena.ne.jp/entry/image/" + urlStr;
  444.  
  445. $("#htbEntryAdd").attr("href", htbEntryAdd);
  446. $("#htbEntryUrl").attr("href", htbEntryUrl);
  447. $("#htbEntryImg").attr("src", htbEntryImg);
  448. }
  449.  
  450. /*
  451. *--------------------------------------------------
  452. */
  453.  
  454. /**
  455. * @title 【キーワードをイメージに置換】
  456. * @description
  457. *
  458. * 画像置換クラスで囲われたキーワードを画像に置換する。
  459. *
  460. * @return なし
  461. */
  462. function kw2Img() {
  463. // 画像キーワードの取得
  464. var imgRep = [];
  465. $(".imgRep").each(function(){
  466. imgRep.push($(this));
  467. });
  468. var imgRepSz = imgRep.length;
  469.  
  470. // 検索処理
  471. cISrch
  472. .reset()
  473. .srch({
  474. // 画像を検索して、キーワードを置換する
  475. type : "img",
  476. loop : imgRepSz,
  477. key : function(){return imgRep[cISrch.loopCnt].text();},
  478. res : function(res, cursor) {
  479. if (res && res.length <= 0) return; // 結果なし
  480.  
  481. // 結果あり
  482. var r = res[0];
  483.  
  484. // HTML文字列の作成
  485. var htmlStr = "";
  486. htmlStr += '<img src="' + r.tbUrl + '"'
  487. + ' width=' + (r.tbWidth * 1)
  488. + ' height=' + (r.tbHeight * 1)
  489. + ' border=0'
  490. + ' title="' + cISrch.srchKw + '"'
  491. + ' id="imgInsrtTb' + cISrch.loopCnt + '"'
  492. + '>';
  493. htmlStr += '<img src="' + r.unescapedUrl + '"'
  494. + ' width=' + (r.tbWidth * 3)
  495. + ' height=' + (r.tbHeight * 3)
  496. + ' border=0'
  497. + ' title="' + cISrch.srchKw + '"'
  498. + ' id="imgInsrt' + cISrch.loopCnt + '"'
  499. + ' style="display: none;"'
  500. + ' onload="chngImg(' + cISrch.loopCnt + ');"'
  501. + '>';
  502.  
  503. htmlStr = '<a href="' + r.unescapedUrl + '"'
  504. + ' target="_blank"'
  505. + '>'
  506. + htmlStr
  507. + '</a>';
  508.  
  509. // HTMLの置換
  510. imgRep[cISrch.loopCnt].html(htmlStr);
  511. }
  512. })
  513. .start();
  514. }
  515.  
  516. function chngImg(n) {
  517. $("#imgInsrtTb" + n).hide();
  518. $("#imgInsrt" + n).show();
  519. }
  520.  
  521. /*
  522. *--------------------------------------------------
  523. */
  524.  
  525. /**
  526. * @title 【短縮URL取得】
  527. * @description
  528. *
  529. * 短縮URLを取得する。
  530. *
  531. * @return なし
  532. */
  533. function getShrtUrl() {
  534. cWSrch
  535. .reset()
  536. .shrtUrl({
  537. // 固定URLを作成して、短縮URLに変換
  538. url : $("#fix_url_raw").val(),
  539. res : function(res) {
  540. $("#fix_url_min").val(res);
  541. }
  542. })
  543. .start();
  544. }
  545.  
  546. /**
  547. * @title 【遅延読み込み】
  548. * @description
  549. *
  550. * HTMLの一部を遅延読み込みする。
  551. *
  552. * 以下、遅延領域のサンプル。
  553. *
  554. * <span class="delay">
  555. * <noscript>No JavaScript</noscript>
  556. * <span class="delayBefore">Now Loading...</span>
  557. * <span class="delayAfter"><!--
  558. * hoge hoge
  559. * --></span>
  560. * </span>
  561. *
  562. * @return なし
  563. */
  564. function loadDelay() {
  565. $(".delay").each(function () {
  566. // 遅延前の表示を消す
  567. $(this).children(".delayBefore").html("");
  568.  
  569. // 遅延後の表示を出す
  570. var repStr = $(this).children(".delayAfter").html();
  571. repStr = repStr.replace(/^<!--|-->$/g, "");
  572. $(this).children(".delayAfter").html(repStr);
  573. });
  574. }
  575.  
  576. /*
  577. *--------------------------------------------------
  578. */
  579.  
  580. /**
  581. * @title 【テスト用】
  582. * @description
  583. *
  584. * テスト用コードを記述する。
  585. */
  586. function test() {
  587. }
Cronus Crown(クロノス・クラウン)のトップページに戻る
(c)2002-2025 Cronus Crown (c)1997-2025 Masakazu Yanai
ご意見・お問い合わせはサイト情報 弊社への連絡までお願いします
個人情報の取り扱い、利用者情報の外部送信について