GCP上のRailsで定期実行させるために作ったRuby Code部分について書いてみました.
Mechanize機能の勉強も兼ねてだったので,いろいろ抜けているものもあるかも.
機能
MechanizeとXPATHを利用して,So-netのゼロSIM使用量確認ページにLoginして今の使用量を取得するRuby Script.
Cronに入れたり,Railsに組み込んだり,して使うことを想定しています.
やること
Step1 : MechanizeからLoginページ取得
Step2 : Login処理
Step3 : 『利用状況確認』ページに移動
Step4 : 『利用状況確認』ページの内容取得
Step5 : HTMLをParseして『今月のデータ使用量(速報値)』を取得
Step1 : MechanizeからLoginページ取得
# Mechanize instance生成
agent = Mechanize.new
agent.user_agent_alias = 'Linux Mozilla'
# LoginページのHTMLをGET
login_page = agent.get('https://www.so-net.ne.jp/retail/u/')
↓ login_page.bodyで取れるHTMLにあるLogin Formはこんな感じ(作成時現在)
<!-- 省略 -->
<form name="Login" action="/retail/u/login?realm=/retail/retail_userweb" method="post">
<table class="inputDataElem">
<tr>
<th>
<label for="simNumber">ログインID<span class="pcCR mL">(半角数字)</span></label>
</th>
<td>
<input type="text" name="IDToken1" class="inputTextL hidden" id="simNumber" maxlength="11" />
<span class="spCR mL">(例:09011112222)</span>
</td>
</tr>
<tr>
<th>
<label for="simPassword">パスワード</label>
</th>
<td>
<input type="password" name="IDToken2" class="inputTextL hidden" id="simPassword" maxlength="16" />
<span class="spCR mL"></span>
</td>
</tr>
</table>
<div class="entryElem">
<label for="" class="submitEntry regular disabled">
<input type="submit" value="決定" class="inner hidden" id="simSubmit" />
</label>
</div>
<input type="hidden" name="IDButton" value="login" />
<input type="hidden" name="IDToken0" value="" />
<input type="hidden" name="goto" value="" />
<input type="hidden" name="encoded" value="false" />
</form>
<!-- 省略 -->
Step2でこのFormに必要な情報をMechanizeからInputしてSubmitする.
Step2 : Login処理
# Formに情報をInput
login_form = login_page.form_with(:name => 'Login')
login_form.IDToken1 = '090xxxxyyyy'
login_form.IDToken2 = 'password'
# Login Buttonを押してFormの内容をPOST
top_page = agent.submit(login_form)
これでLogin処理が完了.Webから操作するよりも素早くLogin処理が完了しているように見える.
Step3 : 『利用状況確認』ページに移動
Login後のTop Pageの『利用状況確認』ページへのLinkまわりはこんな感じ.
<!-- 省略 -->
<ul class="main mainMenu">
<li class="block">
<form name="userUsageActionForm" method="post" action="/retail/u/userUsage/">
<div>
<input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="8a0e887a8ffdeb7db5a69d1a4662af89">
</div>
<label for="menuUseCondition" class="outer">
<input type="submit" name="index" value="ご利用状況確認" id="menuUseCondition" class="inner">
</label>
</form>
</li>
</ul>
<!-- 省略 -->
『利用状況確認』のLinkボタンは内部ではFormになっていて,HiddenのParameterをPOSTしている模様.
このPOSTをMechanizeから発行することでページ移動する.
# UsageのFormを取得してPOST
usage_form = top_page.form_with(:name => 'userUsageActionForm')
usage_page = agent.submit(usage_form)
Step4 : 『利用状況確認』ページの内容取得
↓ ページ移動後の利用状況確認ページのHTMLはこんな感じ.
(生データはなぜか<dd>の中に大量のスペースやTabが入っていたので整形しています)
<!-- 省略 -->
<dl class="useConditionDisplay">
<dt>今月のデータ使用量(速報値)</dt>
<dd>67MB</dd>
<dt>本日のデータ使用量(速報値)</dt>
<dd>6MB</dd>
<dt>昨日のデータ使用量</dt>
<dd>10MB</dd>
<dt class="end">一昨日のデータ使用量</dt>
<dd class="end">51MB</dd>
</dl>
<!-- 省略 -->
あとはこれをParseして"67"とかの情報を取り出してあげればOK.
Step5 : HTMLをParseして『今月のデータ使用量(速報値)』を取得
Mechanizeのsearch関数でXPATHが使えるので,これを使ってHTMLをParseする.
usage_list = usage_page.search('//dl[@class="useConditionDisplay"]')
month_used_current_mb = usage_list.search('dd')[0].text.to_i
puts month_used_current_mb # 今月の使用量(速報値)
まとめ
- So-netのサーバ側のErrorに対応するError Handleがない
- Login Fail時のError Handleがない
- So-netページのID名とかの内部仕様が変わったら破綻する
のような課題はあるものの,一応当初の目的の機能は実装できました.
GCP上のRailsに入れて,cronで定期的に情報取得→移動機に通知,という運用ができています.
///---