Webサイトに自動ログインして情報収集2

SBI証券にログインして口座情報を取得する

前回から少し前進して、ログインしてページ情報をゲットしたいと思います。

リンク情報の取得に悩む

前回も参考にあげたこのページのやり方だと、どうしても例外になってしまう。いろいろ動きを調べると、正しくページが取得出来ていなかったり、HTMLの要素が取り出せていないようだ。
ポイントは
+ 目的のページがロードされるまで待つ処理
+ クリックするリンクをたどる取るためのHTML要素取得
の部分を直す。

WebDriverWait

ページをの取得をする際に、implicitly_wait()関数で待ち時間を指定する方法があるが、WebDriverWait()関数を使って、タイムアウト例外で処理した方が処理が簡単そう。

Elementの取得にはXPathを使う

ChromeでSBI証券のページに行って検証してみると、Aタグ以下にLink textが設定されていないケースもあり、上記参考ページの例ではリンクをたどる要素がうまく取得できないことが分かった。XPATHを使って、下位のimgタグで、altテキストに”口座管理”という文字列を持つ要素を探す、というようにしてみた。

上記二つの対策を立てたコード

user_iduser_passwordには、ログインIDとパスワードを指定して下さい。

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common import exceptions as selExceptions
def fetch_sbi_account_html(user_id,user_password):
    driver = webdriver.PhantomJS()
    print('driver start')
    driver.get('https://www.sbisec.co.jp/ETGate')
    try:
        WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.NAME, "user_id"))
        )
    except selExceptions.TimeoutException:
        driver.quit()
        print("Give up loading start page.")
        quit()
    else:
        print ("Success:load entry page.")
        driver.save_screenshot("screen1.png")

    uid = driver.find_element_by_name('user_id')
    password = driver.find_element_by_name('user_password')
    uid.send_keys(user_id)
    password.send_keys(user_password)

    driver.find_element_by_name('ACT_login').click()
    try:
        WebDriverWait(driver, 20).until(
            EC.presence_of_element_located((By.XPATH, '//img[@alt="口座管理"]'))
        )
    except selExceptions.TimeoutException:
        driver.quit()
        print("Give up loading logined page.")
        quit()
    else:
        print ("Success:load logined page.")
        driver.save_screenshot("screen2.png")

    html = driver.page_source
    driver.quit()
    print('driver quit')
    return html

この関数をuser_idとuser_passwordを設定して呼び出して、screen2.pngというファイルにきちんと中身が出来ていればOK。

次回は、返却されたhtmlを解析して、口座の詳細情報をデータとして取り出します。

Webサイトに自動ログインして情報収集1

金融資産を管理したい

やろうとしていること

  • 銀行や証券の自分の口座にログインする
  • 証券(投信や株)の口数を取得する
  • 評価額を求めて、目標額からの乖離をみて警告
  • 出来れば、上記の定期的実行を自動的に実施
    というのをやりたい

参考にしたページ

準備:パッケージをいろいろいれる

Anacondaで作った環境に突っ込みます。いろんな作業の裏で処理したいのでヘッドレスなPhantomJSというブラウザを使ってみたいと思います。anacondaにパッケージがあったというのもポイント。beautifulsoup4は、HTMLを解析したりするのに使う。

Anacondaで適当に作った環境のTerminalを開いて、以下のようにパッケージを入れていきます。

conda install beautifulsoup4
conda install phantomjs
pip install selenium

試す

とりあえず、seleniumを動かしてみる。

python
Python 3.6.1 |Continuum Analytics, Inc.| (default, May 11 2017, 13:25:24) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from selenium import webdriver
>>> driver = webdriver.PhantomJS()
>>> driver.get('https://www.sbisec.co.jp/ETGate')
>>> driver.save_screenshot("sbi.png")
True
>>> driver.quit()

カレントディレクトリにsbi.pngというファイルが出来て、開いたら、SBIのトップページの画像が出来ていたら成功。

次はSBI証券の口座情報をゲット(未だ書けてません)しようと思います。

Openpyxlによるxlsxファイルの操作

Excelのファイルの編集

Openpyxl パッケージ

Excelのファイルのうち、xlsx、xlsmファイルを操作することが出来るのがOpenpyxlパッケージです。xlrdなど他のパッケージもありますが、古いxlsファイルでは無く、xlsxファイルを扱うならば、このopenpyxlの方が使いやすいのではと思いました。

仕事ではエクセルをたくさん使うと思いますが、これを使えば、いろいろな作業が簡単にならないかと思った次第です。

ファイルのオープンとセーブ

すごくわかりやすいです。既存ファイルのパスが入っている変数をnewFnameとすると、

import openpyxl as ox
wb = ox.load_workbook(newFname)
wb.save(newFname)

日時の情報をセルに設定する

Openpyxlで、単純な数値を扱う場合の例はいろんなサイトにあるようでしたが、日付を扱う場合の例があまりないようでしたので記載します。具体的には、セルにdatetimeパッケージのオブジェクトを設定すると、日付や時間としてセルに値を書き込んでくれます。

import openpyxl as ox
import datetime

wb = ox.load_workbook(newFname)
ws = wb.active

aDate = datetime.date(year=2017, month=6, day=4)
ws['A1']=aDate

表示形式でユーザ定義の書式を設定したい

このままだと、Excel上では2017-06-04のように表示されてしまいます。好みの表示書式に設定するには、cellオブジェクトのnumber_formatプロパティにを使います。

# 申請日 : 2017年 6月 4日(日曜日) みたいな感じになります。
dateformat = "\"申請日 : \"[$-411]ggge\"年 \"m\"月 \"d\"日 ( \"aaa\" 曜日)\";@"
ws['A1'].number_format=dateformat

なお、未だ自分が知らないだけかも知りませんが、セルに値を設定すると様々なプロパティが失われてしまいます。なので、上記の様なフォーマット設定は、値設定後にする必要があります。

罫線を引く、セルの罫線を保持する

罫線は,Borderオブジェクトをcellのborderプロパティに設定することで引けます。
上記に書いたように値設定するとセルの情報が失われるので、先に元の罫線の情報をコピーしておくと良いです。

from copy import copy
border = copy(ws['A1'].border)
ws['A1']=aDate
ws['A1'].border=border

ちなみに

xlsx,docx,pptxなどのMS Officeのファイルって実はzipファイルだって知ってました?。ファイルの拡張子をzipに変更して、解凍する事が出来ます。そうすると、複数のフォルダとxmlファイル等を取り出すことが出来ます。Openpyxlでxmlファイル操作のパッケージを使っているのはそういった理由です。