技術(tech)

基本情報技術者試験勉強に役立つ 〜 毎日LINEで過去問通知

はじめに

基本情報技術者試験の午前勉強に身が入らない方に向けて、
LINEで毎日過去問を通知し、自動的に勉強できるようになる方法をお伝えします。

基本情報の勉強を始めよう! まずは午前問題の勉強から…
でも試験まで時間があるしまだ頑張らなくても大丈夫…
という方も多いのではないでしょうか。

今回の記事では、そんな方々に基本情報の午前問題の勉強をするきっかけを与えます。

この記事を見て出来ること

過去4回分の午前過去問題の中からランダムに選ばれた問題を、
下記画像のように、LINEのグループに対して通知してくれる機能を作ることが出来ます。

スクリーンショット 2020-02-09 22.07.56.png

答えが気になる場合は、続き↓ から過去問サイトに飛びます。

スクリーンショット 2020-02-10 11.43.13.png

そのまま問題を解くことができます。
過去問サイトがとても使いやすいです。

スクリーンショット 2020-02-10 11.42.51.png

通知のタイミングは自分で設定出来ます。
本記事では、1日に2回だけ問題を通知するように設定します。
2回の内訳としては、昼休み(12:00~13:00)と退社中(18:00~19:00)の時間です。

本仕組みを開発したきっかけ

試験がいつなのかを理解していても勉強が進まずに、
気がついたら試験1週間前… 試験前日…となってしまうことがあるのではないでしょうか。

なぜ、勉強が進まないまま、試験当日を迎えてしまうのかを考えると、
書籍や過去問サイトを開いて勉強を始めるという部分が億劫で、
その先のプロセスに進めていない人が多いんじゃないかと考えました。

そこで今回は、基本情報の過去問に触れる機会を自動的に作って
過去問サイトを開くきっかけ(導線)を作ろうと考えました。

execImage.005.jpeg execImage.006.jpeg

アプリの設計

  • 過去問の取得方法:Google Apps Script
    • サーバを立てる必要が無く、準備が楽。
    • これ一つで、過去問のスクレイピングから通知内容のプッシュまで出来る。
  • 過去問の範囲:過去4回分
    • 過去3年分(6回)を抑えたいが、最初から問題範囲を広げすぎたくない
    • 過去1年分(2回)だと期間が短すぎて、通知する問題が重複しそう。
      • 間をとって、過去2年分(4回)にしよう
  • 通知方法:LINE Notifyを用いてLINEグループへ通知
    • 誰か(例えば友達)と勉強する環境を共有したほうが、継続できそう。
    • 分からなかった問題は、チャットに投げてグループ内で話し合える。
  • 通知のタイミング:昼休み中、退社中の2回
    • 携帯を開いているであろう時間。このタイミングなら問題を解いてくれそう。
    • これ以上通知回数を多くすると、うるさくてミュートされそう。
  • 通知内容:問題文 + 解答選択肢
    • 答えまで載せないの?
      • 過去問サイトに飛んで確認して欲しいので、敢えて載せない
    •  なんで過去問サイトに飛んで欲しいの?
      • 通知された1問だけを解いて終わりにして欲しくないから。
        過去問サイトまで飛べば、次の問題を選んで、
        2問目、3問目と続けて解くことができる。

開発環境

  • Line Notify
  • Google Apps Script(GAS)

開発の全体像

本処理の全体像としては、以下のようになっています。
GASで過去問サイトから問題を引っ張ってきて、通知する内容を生成します。
その内容をLINE Notifyに投げることで、
指定したLINEグループに通知が飛ぶ仕組みとなっています。

execImage.001.jpeg

実装

過去問の元ネタ

基本情報技術者試験ドットコムから引っ張ってきています。

LINE Notifyによる通知

まずは、ピンク色の網掛け部分を作成し、
モックとして仮置した内容をLINEグループ通知する仕組みを作ります。

execImage.002.jpeg

手抜きと言われたら何も言えないのですが、
下記の記事をそのまま手順通りに進めることで、
ピンク色の網掛け部分を作成出来ます。
まずは下記の記事を手順通りに進めます。

LINEで自動的にメッセージを定期送信する方法【LINE Notify, Google Apps Script】

手順通りに進めると、LINEグループに下記の画像のような通知ができるようになります。

line-notify-gas-image22.png

Google Apps Scriptの実装

次に、過去問サイトから過去問をスクレイピングして、
通知内容を生成するGASを作成します。

execImage.003.jpeg

全体のソースコードは以下の通りです。
なお、token部分には自分で作成したトークンを貼り付けてください。

function postContent() {
  // 問題年度をランダムに選択
  var seasonList = ["01_aki", "31_haru", "30_aki",  "30_haru"];
  var season = seasonList[Math.floor(Math.random() * seasonList.length)];

  // 乱数で問題作成
  var number = Math.ceil( Math.random() * 80);

  // スクレイピング
  const base = "https://www.fe-siken.com/kakomon/" + season + "/";
  const url = base + "q" + number + ".html";
  //const url = "https://www.fe-siken.com/kakomon/30_haru/q62.html"
  var html = UrlFetchApp.fetch(url).getContentText('Shift_JIS');
  var content = "";
  //Logger.log(url)

  // モバイル版URLを作成
  const baseMobile = "https://www.fe-siken.com/s/kakomon/" + season + "/";
  const urlMobile = baseMobile + "q" + number + ".html";  

  // 問題文を取得
  var question = parseQuestion(html);
  content += question + "\n\n";

  // 選択肢を取得
  var choices = parseChoices(html);
  content += choices + "\n";

  // 回答を取得(未実装)

  // 解説を取得(未実装)

  content += "続き↓\n" + urlMobile + "\n\n";
  sendPostContent(content);
}

function parseQuestion(html) {
  var itemRegexp = new RegExp(/<div>.+<\/div>/g);
  var item = html.match(itemRegexp);
  var question = item[0].replace(/.*<div>/, '').replace(/<\/div.*/, '').replace(/<.*>/g, '');  

  return question;
}

function parseChoices(html) {
  var itemRegexp = new RegExp(/<ul class="selectList cf">.+<\/ul>/g);
  var choices = html.match(itemRegexp);
  //Logger.log(choices);

  // 回答を配列に分割
  if (choices == null) return "";
  var choicesArray = choices[0].replace(/<ul class="selectList cf">/, '').replace(/<\/ul>/, '').split("</li>");
  // 各要素に含まれているdivタグを削除する
  var text;
  var choices = "";
  for (var i = 0; i < choicesArray.length; i++) {
    text = choicesArray[i].replace(/.*<div id="select_.">/, '').replace(/<\/div.*/, '');
    if (text == "") continue;
    choices += (i + 1) + ": " + text + "\n";
  }
  //Logger.log(choices);

  return choices;
}

function sendPostContent(content) {
  var token = ['自分で生成したトークンを記述'];
  var options = {
    "method": "post",
    "payload" : {"message": content },
    "headers": {"Authorization": "Bearer " + token}    
  };
  UrlFetchApp.fetch("https://notify-api.line.me/api/notify", options);
}

ここまで実装すると、LINEグループに過去問を通知出来るようになります。

定時起動設定

残るは、定期的に問題を通知する部分です。
定時起動設定については、GASエディタのUIから設定できます。

execImage.004.jpeg

下記の画像のピンク枠のアイコンをクリックして、トリガー設定画面を開きます。

スクリーンショット 2020-02-10 11.24.58.png

「トリガーを追加」を選択します。
※完全新規で作成する場合には、「新しいトリガーを作成します」を選択します。

スクリーンショット 2020-02-10 11.25.28.png

下記の画像のように設定します。
ここでは、毎日午後12時〜1時の間に一度過去問の通知が飛ぶように設定しています。
同様に午後6時〜7時の通知の設定も追加しましょう。

スクリーンショット 2020-02-10 11.26.40.png

ここまで実施できれば、無事設定完了です。
毎日少しずつ基本情報の午前問題を勉強しましょう!!

既知のバグ

  • 問題文中に<div>が含まれている場合は、上手くパースできていません
  • 問題文 or 解答選択肢が画像になっている場合は、
    LINE Notifyで画像部分を投稿できていません

終わりに

まだまだバグだらけではありますが、
基本情報の午前問題を勉強するきっかけ作りにはなるのではないでしょうか。

勿論、毎日過去問を2問だけ勉強するだけでは、
インプットの量としては足りないと思います。

1問解いて、「あれ? 割とさくさく解けるな… 後もう1問, 2問解いてみようかな…」
と思えるようになれば、毎日のインプット量が少しずつ増えて、
試験当日までには午前を通過出来るまでには
成長出来るのではないかと思ってます。

具体的には、以下の流れで勉強することを期待しています。

  1. LINEの通知が来る
  2. 問題を見る
  3. 続きのリンクから過去問サイトに飛ぶ
  4. 問題を解く
  5. 過去問サイトから次の問題を解く
  6. 5をループ

【午後について】
個人的には午後も過去問ゲーだとは思ってますが、
午前のようにさくさく問題が解けるわけではないので、
ある程度まとまった時間をとって腰を据えて勉強する必要があります。

基本情報技術者は「育成目標として取得してください!」
と掲げているIT企業が多いかと思います。

企業で資格取得を推進する際には、「頑張れ!」と応援する他にも、
勉強の仕組みを作り、提供してあげれば、
推進する側・資格を取る側、お互いハッピーになれるんじゃないかと思いました。
そんな方々に向けても、この記事が何か参考になれば幸いです。

基本情報技術者試験に向けて頑張りましょう!!
※元ネタがあれば、応用情報版も作れると思います。

追記

友達に被験者として使ってもらってますが、
以下の要望があがりましたので、参考程度にどうぞ

  • 昼の時間帯よりも朝の通勤時間帯(8~9時頃)に通知が欲しい
    →確かにそうだよな
  • 問題数をもっと増やして欲しい
    →導線から過去問サイトに誘導するという当初の目的とはずれますが、
    たくさん解きたいと思わせられたことは嬉しい

現在は上記意見を基に、朝と夜に通知が飛び、
一度の通知で2~3問出題するように、GASを修正しました。

修正後のコードはGitHubにアップロードしています。
友人にこの記事がバレたら、「そんなこと思ってたんだ…」と言われそうです笑

お問い合わせはこちらからどうぞ