Python+IFTTTを使ってWiMAXの高速通信の残量をLINEに通知する


動機

 筆者は、現在宅内のインターネット回線としてBIGLOBEのWiMAXを契約して使っています。ちなみに、端末は有線ポートも付いていて電波送受信が高性能なSpeedWi-FiHOMEL02(下図)です。

 WiMAXでは、直近3日間のデータ通信量が10GBを超えると速度制限される制約があります。そのため、その日パソコンを使い始める前に今どれくらい通信残量があるか把握したいと思い、通知システムを考えました。

動作

自宅のWindowsPCでログイン(またはスリープモードから復帰)すると、後述するPythonスクリプトが自動実行されてSpeedWi-FiHOMEL02がローカルに公開している管理ホームページ(下図)から今日までの通信量(図中の赤枠部分)を取得し、そこから今日使える通信量を算出したのち、その値がLINEに通知されます。

 ↑ SpeedWi-FiHOMEL02の管理ホームページ

 ↑ LINEへの通信残量通知

使用した技術要素

  • SeleniumによるWebスクレイピング

 SpeedWi-FiHOMEL02の管理ホームページにある「今日までの通信量」の部分のHTMLなのですが、JavaScriptで動的に書き換えられる要素のため、通常のウェブスクレイピングでは値が"(空白)"となり取得できませんでした。
 そこで使用したのが、Seleniumと呼ばれるブラウザオートメーションツールです。OSにインストールされているブラウザ(本記事ではChrome)を自動操作してWebコンテンツの操作や取得ができ、これであれば動的なHTML要素も取得することができます。導入にあたっては以下の記事が参考になりました。
Python + Selenium で Chrome の自動操作を一通り - Qiita

  • IFTTT(WebhookとLINE)

IFTTTは、Webサービス同士を連携させるサービスです。「もしサービスAが●●したならサービスBが▲▲する」といった動作を記述(これをAppletと呼ぶ)することができるので、今回の場合は
 ・サービスA = Webhook(IFTTTが提供する個人用WebAPI)
 ・●●したなら = 通信残量のデータがPOSTで送られてきたら
 ・サービスB = LINE
 ・▲▲する = データをLINEタイムライン上に通知する

という風にAppletを作成しました。IFTTTの使い方やAppletの作成方法については以下の記事等を参考にしてください。
 さまざまなサービスが連携できる「IFTTT(イフト)」の使い方 (1/3):IFTTT入門 - @IT
 IFTTTの『Webhooks』の使い方を例題で簡単説明【初心者向け解説】

  • Windowsタスクスケジューラ

後述するPythonスクリプトを実行すればLINEに残量が通知されるのですが、パソコンを使い始める、というタイミングで自動的に実行されるようにする必要があります。今回はPCがWindowsだったので、OSの標準機能であるタスクスケジューラを使いました。下記記事が参考になります。
 【Windows 10対応】タスクスケジューラで定期的な作業を自動化する (1/2):Tech TIPS - @IT
 #WindowsタスクスケジューラでPythonを走らせる - Qiita

ただし、上記記事を参考にタスクを作成したあと、自動実行のトリガを編集して「ワークステーション アンロック時」にしました。「ログオン時」でもいいのですが、その場合スリープからパスワードを入力して復帰した際にタスクが起動しなかったためです。

作成したPythonスクリプト

 Python3で作成したスクリプトを以下に記載します。importで記載のあるseleniumchromedriver-binaryは、pipコマンド等でPCにインストールが必要です。また、chromedriver-binaryをインストールする際は、PCにインストールされているChromeのメジャーバージョンとchromedriver-binaryのバージョンを揃える必要があるため要注意です(pipはバージョン指定インストールが可能)。

wimax_alert.py
#! /usr/bin/env python
# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import chromedriver_binary
import traceback
import requests

BASIS_VOLUME = 10.0 #利用可能な上限通信容量(GB)
NOTIFY_TH = 3.0 #残量通知のしきい値(GB)
MYPAGE_URL = 'http://192.168.0.1/html/login.htm' #SpeedWi-FiHOMEのURL


def handleError(location_str): #例外の内容を出力する関数
    print(location_str + "でエラーが発生しました。")
    print(traceback.format_exc()) #エラーの詳細を表示


#ここからスクリプト開始
options = Options()
options.add_argument('--headless') #ウィンドウを出さないモード
chrome = webdriver.Chrome(options=options)
chrome.get(MYPAGE_URL)
#Webページ内のID付要素から今日までの通信量を取得("X.XX GB" or "XXXX.XX MB")
today_usage = 0.0
today_usage_text = chrome.find_element_by_id("today_data_usage").text
chrome.quit()#Chromeを閉じる
if "MB" in today_usage_text:
    today_usage = float(today_usage_text.replace(" MB",""))/1000.0 #GBに変換、少数型にする(X.XX)
if "GB" in today_usage_text:
    today_usage = float(today_usage_text.replace(" GB","")) #少数型にする


remain = BASIS_VOLUME - today_usage
if remain <= NOTIFY_TH :
    remain = '{:.2f}'.format(remain) #通信残量を少数第2位までに丸める
    #IFTTTのWebfookに送信(IFTTT側の設定によりLINEにポストされる)
    url = "https://maker.ifttt.com/trigger/wimax_alert_notified/with/key/{IFTTTのWebhook個人キーを入力}"
    try:
        response = requests.post(url,data={'value1':remain})
    except:
        handleError("IFTTTへの送信")

NOTIFY_THは、通信残量がこの値以下なら通知する、という閾値です。この値を大きくすれば通知頻度が高くなり、小さくすれば通知頻度が低くなります。
{IFTTTのWebhook個人キーを入力}の部分には、個人のIFTTTWebhookキーを指定する必要があります。
また、本スクリプトを実行する際は、上述した通りIFTTTにてWebhookを受け取りLINEで通知するAppletを作成しておく必要があります。

所感

 本通知システムにより、ログイン時に今日使える残量が把握できるので、うっかりYoutubeやAmazonPrimeで動画を見過ぎて次の日の通信残量が1~2GBしかない、という事故を未然に防ぐことができます。
 SpeedWi-FiHOMEL02の管理ホームページでのWebスクレイピングについて、深く考えずにPythonで確立されているこれまでの方法が通じる、と当初考えていたところ、通信残量のHTML要素が空白しか取得できずに躓きました。(独学でVue.jsを学んでいるため、データがJavaScriptで動的に書き換えられているということはなんとなく理解できた)
 その解決方法として、OSにインストールされているブラウザを自動操縦する新しいタイプのWebスクレイピングに関する知見が得られたため、他の自動化のアイデアにも応用していきたいです(ログインが必要な電力会社のマイページから電気代の明細を自動ダウンロードするとか?)。