Hatena::ブログ(Diary)

とりあえず日記 このページをアンテナに追加 RSSフィード Twitter

2017-11-18

イオンモバイルの利用料金をスクレイピングした。(Python+selenium)

経緯

私が契約しているイオンモバイルでは、請求金額を通知するサービスを行っていません。(※)

なので、今まで個人ページで毎月確認していました。

さすがに繰り返しの手作業が面倒になったので、自分の個人ページをスクレイピングして毎月の請求金額をメール通知するようにしました。

(※)イオンモバイルでは請求金額を通知するサービスはありますか? | よくあるご質問|業界最安級 イオンの格安スマホ・格安SIM【イオンモバイル】

以下は、請求金額のページをスクレイピングする最小のソースコードと使い方です。

スクリプトの実行方法

コマンドプロンプトで以下のように実行。

>python.exe aeon_mobile.py お客様ID パスワード

実行結果

コマンドプロンプトに明細をダンプ表示します。

数値が揃っていなくて見にくいですが、細かなことは気にしない!!!

料金は個人情報なので適当に書き換えてます。

**2017年 11月分**
金額(税込)1,234円


**料金明細**
4GBプラン                             123円
追加音声シェア料金                              456円
通話料                          78円
SMS通信料                               9円
イオンでんわ割引通話(国内)                            10円
ユニバーサル料                          11円
イオンでんわ 10分かけ放題                               123円

ソースコード(python+selenium)

aeon_mobile.py というファイル名で保存してください。

"""utf8-bom
イオンモバイルの利用料金をスクレイピングするサンプル。

usage:
python.exe aeon_mobile_pay.py お客様ID パスワード

"""
import sys
from selenium import webdriver
import selenium



#ご利用明細
class Detail(object):
    __slots__ = ("title","money")
    def __init__(self,title="",money=""):
        #プラン名、通話料、通信料・・・
        self.title=title
        #金額
        self.money=money

#月の明細
class InvoiceDetail(object):
    __slots__ = ("month","money","details")
    def __init__(self,month="",money=""):
        #年月
        self.month=month
        #金額(税込)
        self.money=money
        #料金明細
        self.details=[]

    def to_plane_text(self):
        pool=[]
        pool.append("**%s**"%self.month)
        pool.append("金額(税込)%s" % self.money)
        pool.append("\n")
        if not self.details:
            return "\n".join(pool)

        pool.append("**料金明細**")
        for item in self.details:
            pool.append(item.title + "\t\t\t\t" + item.money)

        return "\n".join(pool)


def jump_usage_details_page(driver):
    """ご利用明細のページに切り替える。
    """
    try:
        driver.find_element_by_link_text('ご利用明細').click()
        return
    except(selenium.common.exceptions.NoSuchElementException):
        pass

    #ウインドウ幅が狭くナビゲーションの文字が表示されていない状況なので、
    #左上のボタンをクリックしてメニューを開く。
    driver.find_element_by_xpath('/html/body/div[1]/nav/div/a[2]/i').click()

    #see. https://teratail.com/questions/64684
    elem=driver.find_element_by_xpath('//*[@id="nav-mobile"]/li[2]/a')
    driver.execute_script("arguments[0].click();", elem)


def scraping(driver):
    #
    #ご利用明細のページをスクレイピングする。
    #
    invoice = InvoiceDetail()
    jump_usage_details_page(driver)
    if True:
        #
        #最新の月を処理する。
        #
        invoice.month = driver.find_elements_by_class_name("strong")[0].text
        invoice.money = driver.find_elements_by_class_name("zeikomi")[0].text
        driver.find_elements_by_class_name("link_button")[0].click()
    elif False:
        #
        #1つ前の月
        #
        invoice.month = driver.find_elements_by_class_name("strong")[1].text
        invoice.money = driver.find_elements_by_class_name("zeikomi")[1].text
        driver.find_elements_by_class_name("link_button")[1].click()
    else:
        #
        #2つ前の月
        #
        invoice.month = driver.find_elements_by_class_name("strong")[2].text
        invoice.money = driver.find_elements_by_class_name("zeikomi")[2].text
        driver.find_elements_by_class_name("link_button")[2].click()

    #
    #ご利用明細を取り出す
    #

    #memo
    #[0]    ご利用金額合計(税込)・・・のテーブル
    #[1]    サービス名・・・のテーブル
    details=driver.find_elements_by_tag_name("tbody")[1]
    for tr in details.find_elements_by_tag_name("tr"):
        td = tr.find_elements_by_tag_name("td")
        #サービス名
        service_name = td[0].text
        #金額
        mony = td[1].text
        invoice.details.append(Detail(service_name,mony))

    return invoice


def main(id,pw):
    driver = webdriver.Chrome('C:\selenium\chromedriver')
    driver.get('https://mypage.aeondigitalworld.com/mypage/')

    #ウインドウサイズを小さくする(debug)
    #driver.set_window_size(640,480)

    #ログイン処理
    driver.find_element_by_name('userId').send_keys(id)
    driver.find_element_by_name('password').send_keys(pw)
    o=driver.find_element_by_xpath('//button').click()
    invoice = scraping(driver)
    driver.quit()

    print(invoice.to_plane_text())


if __name__ == '__main__':
    id=sys.argv[1]
    pw=sys.argv[2]
    main(id,pw)


注意

スクレイピングを推奨する意図はありません。

ソースコードなどのご利用は自己責任でお願いします。

2017-11-13

【解決】「SONY Xperia J1 Compact +MacBookAir+USBテザリング」でインターネットに接続できない。

現象

MAcBookAirでスマホUSBテザリングを行うと、スマホWIFI経由だとインターネットに接続出来るがLTE回線だと接続出来ない。

接続方法

MacBookAir -> USB -> スマホ(SONY Xperia J1 Compact)

解決方法

Androidでファイヤーウォールとして動作する、NoRootファイアウォールアンインストールしたらインターネットに接続出来ました。

このアプリVPN接続を利用するので何か悪さしていたのかも・・・

https://play.google.com/store/apps/details?id=app.greyshirts.firewall&hl=ja:title=

]

環境

スマホSONY Xperia J1 Compact

ノートPC:MacBookAir+USBテザリング

補足

MacBookAirはHoRNDISとXperia Companionをインストールして、

USBテザリングが出来るようにしています。

Mac + AndroidでのUSBテザリングの設定で手間取ったので手順メモ

Mac OS El Capitan で Android USB tethering (HoRNDIS) - Qiita

2017-10-29

seleniumとpywinautoでChromeのWEBページを印刷する。

f:id:ohtorii:20171031172311p:image:w360

背景

我が家では嫁が家計簿を付けているので、毎月クレジットカードの利用明細を紙に印刷して提出しています。

嫁がアナログな人なので「紙で提出して!」と言って聞かないのです・・・

毎月繰り返し手作業で利用明細を印刷するのが、さすがに面倒になってきたので自動化する事に決めました。

発生した問題

このような、繰り返しのジョブ実行はjenkinsさんにおまかせするとして・・・

今回の最大の問題点はseleniumとchromeブラウザの組み合わせでは、そもそも印刷ダイアログが開かないことでした。

WEBを検索すると幾つかの解決策がありますが、私の環境ではどうやっても印刷ダイアログが開きませんでした。

(WEBの情報)

以下のどれを試しても印刷ダイアログは開きませんでした。

  • driver.find_element_by_tag_name('body').send_keys(Keys.CONTROL,'p')
  • ActionChains(driver).send_keys(Keys.CONTROL, 'p').perform()

以下は、printメソッドを実行することで印刷ダイアログが開きますが、

印刷の詳細設定を行う方法が分からず、私の実力では手詰まりになりました。

  • driver.execute_script('window.print()')
  • driver.execute_async_script('window.print()')

問題の解決方法

そこで、Windowsの操作を自動化するpywinauto(pythonモジュール)を利用して印刷ダイアログの制御を行いました。

seleniumではブラウザの制御を担当させて、pywinautoには印刷ダイアログの制御を担当させました。

(処理の流れ)

[selenium]chromeブラウザを開く。

[selenium]クレジットカードの利用明細ページへのログイン

[selenium]利用明細ページへ移動する。

[pywinauto]印刷ダイアログを開き、印刷設定を行ってから印刷を行う。

[pywinauto]印刷ダイアログを閉じる。

[selenium]chromeブラウザを閉じる。

サンプルコード

import time,pywinauto
from selenium import webdriver

def main():
    driver = webdriver.Chrome('C:\selenium\chromedriver')
    driver.get(クレジットのログインページ)

    #ログイン処理を行う。(省略)
    
    #利用明細のページへ移動する。(省略)

    #印刷処理
    print_dialog()

    #適当に待機しないと印刷が開始されない。
    #ブラウザのテキストや画像をプリンターに送信している最中にブラウザを閉じる(driver.quit)と印刷が開始されないようだ。
    time.sleep(5)

    driver.quit()


def print_dialog():
    #
    #印刷ダイアログを開いてページ指定してから印刷する。
    #

    pywinauto.keyboard.SendKeys("+^P")

    a_check = lambda:pywinauto.findwindows.find_windows(title=u'印刷', class_name='#32770')[0]
    dialog = pywinauto.timings.WaitUntilPasses(5, 1, a_check)

    pwa_app = pywinauto.Application()
    pwa_app.connect(handle=dialog)

    window = pwa_app[u'印刷']
    window.Wait('ready')

    button = window[u'ページ指定(&G):']
    if button.is_enabled():
        #印刷範囲を指定する。
        button.Click()
        edit = window.Edit4
        edit.SetFocus()
        edit.set_text("1-2")

    #印刷ボタンを押す(Alt+P)
    pywinauto.keyboard.SendKeys("%P")
    
    #印刷ボタンを押すと印刷ダイアログは自動的に閉じるのでここでは何もしない。


if __name__ == '__main__':
    main()    

まとめ

とりあえず目的は達成しましたが、もっと良い方法があるかもしれません。

Seleniumは初めてなので今回はこれで良しとしました。


環境

  • Windows10 64bit
  • Python 3.6.3 64bit
  • Selenium 3.6.0
  • ChromeDriver 2.33.506120
  • pywinauto 0.6.1
  • chrome バージョン: 61.0.3163.100(Official Build)(64 ビット)

参考ページ

http://sjpknight.com/automating-pdfs-and-windows-objects-with-python-and-webdriver/

Seleniumで印刷(print preview)を経てPDFを保存する方法 - それマグで!

参考書籍

2017-10-02

macOS High SierraでAudirvanaのDirectModeを利用する

MacBookAirをmacOSSierraからmacOS High Sierraアップデートしたところ、AudirvanaのDirectModelが利用できなくなりました。

前回(id:ohtorii:20170716)の手順でDirectModeを利用できるようになりました。

環境

Audirvana Plus 2.6.8

macOS High Sierra 10.13

Esoteric D-07

2017-08-22

Walkman(NW-A36HN)で音切れが発生する

NW-A36HNを購入しました!

がっ、MP3を再生中に時々音切れが発生して大変困っています・・・

サポートへ問い合わせています。

音切れについて

「世界に一つだけの花〜〜♪」という歌詞が、

「世界に一つだだだだだだだだだだだだだだだだだだだだだだだだだだだだだだけの花〜〜♪」というふうに再生されます。

頻度など

  • 10〜20分毎に発生しています。
  • 特定のMP3ではなく色々なMP3で発生しています。
  • 音切れの発生したMP3を再度再生すると正しく再生されるため、MP3ファイルが壊れていることはありません。
  • 電源ボタンを長押しして本体の再起動を行っても音飛びは発生します。

音切れが発生するMP3について

  • 保存先メモリー:本体メモリー
  • 320kbps 44.1Khz 16bit
  • 歌詞データ無し

Walkmanの環境

ネット上の情報

本体ソフトウェア1.20で音飛びが改善されていないという書き込みが価格comにありました。

2017年8月24日更新

サポートから返信がありました\(^O^)/

がっ!

何故か音切れが再現しなくなりました。

2017年12月4日更新

音切れが再発しました。

以下は、音切れが発生したときの手順です。

  • ClearAudioをONからOFFにする。
  • VTP(サラウンド)をONにする。
    • タイプ選択のメニューからサラウンドの種類を適当に選択してから、コンサートホールを選択する。
  • イコライザーをONにする。
    • プリセット選択のメニューを適当に選択してから、EDMを選択する。
  • DSEE HX をOFFからONにすると、音切れが10秒くらい発生しました。

音切れ中は画面をクリックしても反応しませんでした。

音切れ後は普通に再生が行われます。

上記の手順を3回試しましたが再現はしていません。

Walkmanを購入してからずっと再現方法を探してる気がする・・・

職業がプログラマーなので音楽を聞くよりも再現方法を探る方が楽しいからいいけどね。