4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

MyDocomoから今月の通信量を取得してLINEで通知する

Last updated at Posted at 2019-05-01

やったこと

1日1回、MyDocomoから今月の通信量を取得してLINE Notifyでお知らせするプログラムを作りました。
また、これをHerokuで定期実行する環境を作りました。

使ったもの

1日1回実行するために...

  • Heroku
  • Heroku Scheduler

今月の通信量を取得するために...

  • Python3 (言語)
  • Selenium (ブラウザ自動操作ツール)
  • Chrome (ブラウザ)
  • Chrome Webdriver (Chromeを自動操作するためのドライバ)

作成したファイル

今回作成したファイルは以下のとおりです。

$ ls
Procfile
main.py
requirements.txt
README.md
mydocomo.py

Procfile

Procfileは、Herokuのプラットフォーム上にあるアプリケーションのdynosにより実行されるコマンドが 何であるかを宣言するためのメカニズム
(https://github.com/herokaijp/devcenter/wiki/procfile より引用)

Procfile
web: python main.py

main.py

Webアプリに適用するダミーのコード。
よく分かってはいませんがWebアプリにはダミーを置いておくもののようです。
おそらく、誰かにWebアプリに対してリクエストを送られたタイミングで定期実行用のプログラムが動かないようにするため?だと解釈しています。

main.py
# -*- coding: utf-8 -*-

import os
from bottle import route, run


@route("/")
def hello_world():
    return "" # ここで返す内容は何でもよい

run(host="0.0.0.0", port=int(os.environ.get("PORT", 5000)))

requirements.txt

必要なライブラリを記載しておくファイル。
これに記載したライブラリは、デプロイのたびにHerokuの環境へ自動インストールされるらしい。便利。
pipをインストール済みの場合、↓のコマンドを打つとインストール済みのライブラリを出してくれて楽でした。

$ pip freeze -l > requirements.txt
requirements.txt
astroid==2.2.5
beautifulsoup4==4.7.1
bottle==0.12.16
certifi==2019.3.9
chardet==3.0.4
chromedriver-binary==74.0.3729.6.0
Click==7.0
colorama==0.4.1
Flask==1.0.2
future==0.17.1
idna==2.8
isort==4.3.16
itsdangerous==1.1.0
Jinja2==2.10
lazy-object-proxy==1.3.1
line-bot-sdk==1.8.0
MarkupSafe==1.1.1
mccabe==0.6.1
PyLink==0.3.3
pylint==2.3.1
pyserial==3.4
requests==2.21.0
rope==0.14.0
selenium==3.141.0
six==1.12.0
soupsieve==1.9
typed-ast==1.3.1
urllib3==1.24.1
Werkzeug==0.15.2
wrapt==1.11.1

インストール済みのライブラリが全て出てくるので、今回の実行には不要なライブラリも含まれちゃうみたいです。

README.md

なくても良いので割愛します。

mydocomo.py

定期実行するプログラム本体。
MyDocomoにログインする際のID、PW、LINE Notifyのトークンは、Herokuの環境変数に設定しました。

mydocomo.py
# coding: UTF-8
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import chromedriver_binary
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import os
import requests
import sys

# 環境変数からトークンなどの情報を取得
notify_access_token = os.getenv('NOTIFY_ACCESS_TOKEN', None)
docomo_id = os.getenv('DOCOMO_ID', None)
docomo_pw = os.getenv('DOCOMO_PW', None)
if notify_access_token is None:
    print('Specify NOTIFY_ACCESS_TOKEN as environment variable.')
    sys.exit(1)
if docomo_id is None:
    print('Specify DOCOMO_ID as environment variable.')
    sys.exit(1)
if docomo_pw is None:
    print('Specify DOCOMO_PW as environment variable.')
    sys.exit(1)

# 通信量の取得
def getLog():

    # Selenium用オプション
    op = Options()
    op.add_argument("--disable-gpu")
    op.add_argument("--disable-extensions")
    op.add_argument("--proxy-server='direct://'")
    op.add_argument("--proxy-bypass-list=*")
    op.add_argument("--headless")

    driver = webdriver.Chrome(chrome_options=op)
    driver.get('https://www.nttdocomo.co.jp/auth/cgi/mltdomanidlogin?rl=https%3A%2F%2Fwww.nttdocomo.co.jp%2Fmydocomo%2F')

    # ID入力
    id = driver.find_element_by_id("Di_Uid")
    id.send_keys(docomo_id)

    # 「次へ」クリック
    login_button = driver.find_element_by_name("subForm")
    login_button.click()

    # PW入力
    password = driver.find_element_by_id("Di_Pass")
    password.send_keys(docomo_pw)

    # 「ログイン」クリック
    login_button = driver.find_element_by_name("subForm")
    login_button.click()

    # 通信量のページへ遷移
    driver.get("https://www.nttdocomo.co.jp/mydocomo/data/")
    dataSpan = WebDriverWait(driver, 10).until(
        EC.visibility_of_element_located((By.CSS_SELECTOR, "#mydcm_data_data-08 > div > dl > dd > p.mydcm_data_data-09-1 > span.card-t-ssnumber.t-bold.mydcm_data_data-10-1"))
    )
    return dataSpan.text

def main():
    mount = getLog()

    url = "https://notify-api.line.me/api/notify"
    token = notify_access_token
    headers = {"Authorization" : "Bearer "+ token}

    message =  '今月の通信量は ' + mount + ' GBです。'
    payload = {"message" :  message}

    r = requests.post(url ,headers = headers ,params=payload)

if __name__ == '__main__':
    main()

Herokuの設定

GUIが大好きなのでHerokuのアプリケーションのページから設定しました。
Heroku CLIをインストールしてCUIで設定しても良いです。

buildpackの追加

Heroku上でChromeとChrome Webdriverを使うためにbuildpackというものを追加します。
SettingsタブのbuildpacksからAdd buildpackをクリックして、以下のURLを1つずつ追加します。

https://github.com/heroku/heroku-buildpack-google-chrome.git
https://github.com/heroku/heroku-buildpack-chromedriver.git

環境変数の設定

SettingsタブのConfig VarsからReveal Config Varsをクリックして、以下の変数を追加します。

変数名
CHROME_BINARY_LOCATION /app/.apt/usr/bin/google-chrome
CHROME_DRIVER_PATH chromedriver
DOCOMO_ID hogehoge@hogehoge.com(MyDocomoのID)
DOCOMO_PW hoge(MyDocomoのパスワード)
NOTIFY_ACCESS_TOKEN 取得したLINE Notifyのトークン
TZ Asia/Tokyo

TZは今回設定しなくても良いですが、合わせておいた方が何かと便利かと思います。

※とりあえず動作テスト

ここまで設定しておいてデプロイすれば、(おそらく)一旦は動くようになっていると思います。
コンソールからmydocomo.pyを実行してみます。
Herokuのアプリケーションのページの右上にあるMoreから、Run consoleをクリックし以下のコマンドを実行します。

python mydocomo.py

Herokuのサーバーがスリープ状態だと実行までに時間がかかるみたいです。
しばらく待ってもLINEの通知が来なかったらLog等を確認してみてください。
問題なければ30秒も待てば通知が来ると思います。

Heroku Schedulerの設定

※Heroku Schedulerのインストール方法は割愛します。

ResourceタブのHeroku Schedulerをクリックし、ジョブの管理画面を開きます。
ジョブの管理画面でAdd Jobをクリックします。

Schedule

ScheduleEvery day at...を選び、
時間は私の場合、3:00 PMを選びました。

設定する時間は世界協定時での設定になるため、
日本の時刻は設定する時間+9時間で考えます。
→UTC午後3時を設定すると、日本時刻では午前0時となります。

Run Command

Run Commandは先程の動作テストで流したコマンドです。

python mydocomo.py

これで毎日0時に今月の通信量がLINE Notifyに通知されるようになります。

課題

Pythonの勉強がてら試しに作ったので取得するデータは今月の通信量だけですし、通知されるメッセージも簡素です。
多少の実用性を考えるのであれば、使いすぎた日の翌日だけ通知するとかにした方が良さそうです。

参考ページ

大変お世話になりました。

4
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?