<初心者>vue.jsでリンクの動的生成とルーティング。おまけでPythonによる頻出語のピックアップ。


やったこと

以前作ったwebサービスに機能追加しました。

サービスの詳細はこちらの記事参照ください。「<初心者>レファレンス協同データベースの記事をランダムに表示するWEBサービスをvue.jsで作りました。

記事の詳細ページにキーワードの項目を設けて、クリックすると検索画面に飛ぶようにしました。

なぜやるのか

現状の問題点

前回記事(cssのアニメーションで検索ボックス上部にレコメンド事例紹介機能を搭載してみた。[2019/07/13追記※3回])と同様、「レファレンスサービス利用経験者が少ないため、どんな事例があるかわかりにくい。」という欠点があります。

今回採用する改善方法

そこで、一つの記事を読んだあとに関連する記事を見てもらえるようにキーワードのタグを作成。タグによって新たな検索行動を促すことで、サイト内での回遊率アップに繋げます。

キーワードは、レファレンス協同データベースの各記事のおそらく半数近くには設定されているのでこれを利用します。設定されていない記事も多いので、プラスαとしてPythonによる頻出単語のピックアップも行いました。しかし、Pythonについてはまだ実装はしていません。

実装方法

シンプルです。

詳細ページにおける他の項目と同様、xmlからキーワードを取得します。

Detail.vue
const keywords = result.getElementsByTagName("reference")[0].getElementsByTagName("keyword")||

ページに反映する際にリンクを設定。

Detail.vue
      <h3 id="keyword">キーワード</h3>
      <span v-for="keyword in refqa.keywords" class="tag" v-bind:key=keyword>
        <a v-bind:href="'https://testreftika.web.app/keyword/' + keyword">{{keyword}}</a>
      </span>

リンクはルーターでトップページに飛ばす

router.js
{
  path: '/keyword/:keyword',
  component: Home
},

トップページでは、リンクを解釈します。/keyword/hogeであれば、hogeを検索ボックスに入力。

Home.vue
created: function() {
    省略
    if(this.path.match(/\/keyword\/./) ){this.keyword=this.$route.params.keyword}
}

上記パス(this.path)はjavascriptで取得している。

Home.vue
  data() {
    return {
      省略
      path:location.pathname,
    }

検索ボックスに入力語は自動で検索されるように実装している。前回記事「cssのアニメーションで検索ボックス上部にレコメンド事例紹介機能を搭載してみた。[2019/07/13追記※3回]」参照。

Home.vue
クリックしたときに、検索ボックスにキーワードを入力するメソッド
setInputBox(searchtext){
      document.getElementById( "searchbox" ).value = searchtext;
      this.keyword=searchtext;   ←この後、this.keywordを監視しているメソッドが検索を実行する
    },

プラスα:Pythonによる頻出語のピックアップ

大まかな流れ

①xmlでデータ取得
②mecabで名詞・形容詞のみピックアップ&stopwordを除外して単語をリスト化
③Counterでリストの各要素の出現個数をカウント、出力

全文です。

import MeCab
from collections import Counter
import urllib.request
import xml.etree.ElementTree as ET

#②mecabで名詞・形容詞のみピックアップ&stopwordを除外して単語をリスト化する関数
def get_dokuritsugo_by_mecab(text):
    tagger = MeCab.Tagger('/usr/local/lib/mecab/dic/mecab-ipadic-neologd/')
    tagger.parse('') 
    node = tagger.parseToNode(text)
    word_list = []
    while node:
        pos = node.feature.split(",")[0]
        if pos in ["名詞", "形容詞"]:
            word = node.surface
            if not word in stoplist:
                word_list.append(word)
        node = node.next
    return(word_list)

#ストップワードについては下記
with open('stopword.txt', 'r', encoding='utf-8') as file:
    stoplines = file.readlines()
    stoplist = []
    for l in stoplines:
        stoplist.extend(l)

#①xmlでデータ取得。「。」で区切り一文ずつmecabを呼び出している。
url = 'http://crd.ndl.go.jp/api/refsearch?type=reference&query=sys-id=1000161493'    ←apiの呼び出し
req = urllib.request.Request(url)

with urllib.request.urlopen(req) as response:
    XmlData = response.read()
    root = ET.fromstring(XmlData)
    QAtext = root[4][0][0].text + root[4][0][2].text
    #※レスポンスのxmlの仕様です。
    #※root[4][0][0]に質問、root[4][0][2]に回答が入っています。
    print(QAtext)

    texts = QAtext.split('。')
    list = []
    sentences = []
    for text in texts:
        list.extend(get_dokuritsugo_by_mecab(text))
        c = Counter(list)
    #③Counterでリストの各要素の出現個数をカウント、出力
    print(list)
    print(c.most_common()[0])
    print(c.most_common()[1])
    print(c.most_common()[2])

ストップワードは、
英語は、sklearn.feature_extraction、日本語はslothlibを使用させていただきました。2つをローカルでtxtファイルにがっちゃんこした上で、記号を付け加えて利用しています。

出力結果

くしゃみの回数で意味が違うという迷信を友人と話していると解釈が違いました。何種類かあるのでしょうか。(北九州市立中央図書館)では、

('くしゃみ', 23)
('噂', 5)
('風邪', 5)

インドの教育事情と教育に関わる社会問題について分かる資料(日本貿易振興機構アジア経済研究所図書館)

('教育', 8)
('インド', 7)
('請求', 5)

※「請求」は図書の「請求記号」という文言が多数使われているため多くなっている。

「この道をいけばどうなるものか」から始まる言葉の全文が知りたい。良寛の言葉らしい。(福井県立図書館)

('言葉', 7)
('詩', 5)
('一休宗純', 5)

記事との偶然の出会いをつくるサービスとしては、そこそこ十分な結果かと思われます。

「請求記号」「国立国会図書館」など、図書館で頻繁に使用される語は除くように調整すれば使えるかもしれません。応答速度などを見ながら、今後試していきます。

参考:
◆mecabのインストール(Windows)
PythonとMeCabで形態素解析(on Windows)
◆mecabの使い方
B'zの歌詞をPythonと機械学習で分析してみた 〜LDA編〜
◆NEologd辞書のインストール
WindowsでNEologd辞書を比較的簡単に入れる方法

◆PythonのCounter
PythonのCounterでリストの各要素の出現個数をカウント
◆PythonとXML
PythonでXMLをパースする

今回は単純な頻出語で行ったが、調べるうちにTF-IDFによる重みづけやJaccard係数を使用した共起ネットワークも気になった。
検索機能に用いられている、特徴語とそのさまざまな抽出方法
世界のラーメンスタイルをNetworkXで可視化する
Pythonを使って文章から共起ネットワークを作る

reftikaもぜひのぞいてみてください。