Binary Diary

今を一番楽しんでいこうMy Life

メンサを受けたいのに受験申し込みという難関を突破できないのでスクレイピングすることにした

どうもこたにんです。


メンサってご存知でしょうか?

かっこよい感じの憧れるやつですね、IQ高いぜって指標になるやつ。
一度は受けてみたいな、って思ってます。

一度は受けてみたいな、って思って結構経ちまして。
思うだけじゃなくてちゃんと受けようと決めました。

そしてホームページを見てみるとですね、こうなんですよ。

f:id:Kotanin0:20190106020449p:plain
満員、満員。
それは人気の受験なのだろうか、枠が少ないのだろうか。
いずれにせよ、いつ何時サイトを訪れても、満員。

んー、これは困った。
受験したいのに、受験申し込みができない。
毎日サイト見に行っても変わらない、チャンスすらない。
毎日サイトを見に行く気力が失われていく。。。


よし!スクレイピングしちゃお!

というわけで、自動化自動化。

今回やりたいこと

JAPAN MENSAの受験申し込みページの東京都の申込状況が空いてるかどうかを、定期的にチェックし、空いてたら通知を飛ばす。


申し込みページの空きを見るには、HTMLを解析すれば良さそうです。
スクリプトだったらゴリッと書けそうです。
これくらいであれば、Google Apps Script (GAS) 書いてトリガー指定すればいけそうですね。
なので、今回はGASで実装する方向でいきましょう。

技術的な方法は以前、別記事で言及したのでそちらを参照。

 

スクリプトを書く

今回は、冒頭に貼ったページのキャプチャの申し込みボタンの開閉を判定したい。
HTMLソースがどうなってるかをまず確認します。

<ul class="list">
  <li class="pref">
    東京都<br />
    <b>1/10</b>
  </li>
  <li class="date">
    日時 : 2019/01/10(木) 19:00~20:00<br />
    場所 : 東京都表参道<br />
    このテストには、埼玉県の方以外がお申込みいただけます。埼玉県の方は、同月開催の埼玉テストをご利用ください。
  </li>
  <li class="link">
    <img src="skin/default/image/exam/entry_quota.jpg" alt="満員" />
  </li>
</ul>

ひとつの申込みのパーツでこんなかたちになってました。
ulの中にliがみっつ、都道府県・日付・申し込みボタン。
都道府県で東京都だけぶつけて、申込みボタンの開閉を見れば良さそう。

もし申込みボタンが空いてたら、こうなっているらしい。

<li class="link">
  <a href="exam/index/notice/id/313/"><img src="skin/default/image/exam/entry_out.jpg" alt="申し込む" style="cursor: pointer;"></a>
</li>

aタグ入ってたり、img alt属性が「申し込む」になってたりしますね、判別できそう。

これらをParser使ってさくっと判別、作りきったスクリプトをぺたり。

function myFunction() {
  var html = UrlFetchApp.fetch('https://mensa.jp/exam/').getContentText();
  var ulList = Parser.data(html).from('<ul class="list">').to('</ul>').iterate();
  
  for each(var ul in ulList) {
    var liPref = Parser.data(ul).from('<li class="pref">').to('</li>').build();
    if (liPref.indexOf("東京都") === -1) {
      continue;
    }
    
    var liLink = Parser.data(ul).from('<li class="link">').to('</li>').build();
    if (liLink.indexOf("申し込む") > -1) {
      sendSlack();
      break;
    }
  }
}

ulを配列で取っておいて、その中で東京都探して、ボタン空いてるか見る。

ガード節で書くと可読性高いコードになるね。
ガード節とは、if判定をするときに、除外したものを判定して後続処理に行かせないこと。
今回で言うと、東京都だったらボタンの空きを見たい、という状況です。
なので、東京都じゃないならcontinueというのを先に書いてしまう、これがガード節。
普段から意識しておくといいかもね?

通知を飛ばす部分は今回は省略します。
WebHookでもなんでもいいじゃん、数多記事は転がってそうだから。
(ふと思ったけどGAS用のSlack送信ライブラリ自分用に作ろ)

ということでスクリプトができたので、これをトリガー設定します。
トリガー設定についても 以前の記事 で言及してるので省略。

できた

申し込み枠が開かない限り通知が飛んでくることはないが、飛んできたら本気出す。
きっとたぶんこんな通知が届くはず(debug時にはガンガン飛んできた)

f:id:Kotanin0:20190106232803p:plain

 

追記

「こちらのしくみで自分の端末に通知をして欲しい!」
という方へ。
クラウドワークスやらランサーズやらで発注せずとも、対応します!

Twitter DMにて個別にご連絡もしくはメールをいただければと。
詳細はメッセージにて詰めさせていただければと。