はじめに
こんにちは。今回は以下のBlackRockのWebページにあるHDVの構成銘柄一覧をダウンロードするプログラムを書いてみました。
www.blackrock.com
HDVとは米国ETFの1つで、複数の米国株を任意の割合で集めた投資商品のことです。
1つ1つの個別銘柄を購入しなくとも、HDVに投資することでこのETFに含まれている複数の銘柄に分散投資ができる、というわけです。
ここではあくまでもプログラムの話メインなので、これ以上の説明は省略します。
動作環境
使用する言語はPython3で、動作させる環境は以下の通りです。
OS:CentOS 7.8 (2003)
プログラミング言語:Python3.6.8
ブラウザ:Firefox78.6
スケジューラ:cron
CentOSはVPS上にインストールして24h稼働させています。
もちろん自前のPCにCentOSをインストールして実行することも可能です。
しかし、自前のPCを自宅で24h稼働させておくといろいろ心配なので(火事とか)、手軽で低価格なVPSを使用しています。
現在私が使っているVPSについては以下の記事に書いていますので、よかったら読んでみてください。
www.77-lifework.com
処理の流れ
では処理の流れですが、以下です。
- ブラウザ(FireFox)を起動し、BlackRockのHDVのURLを開く
- 保有銘柄一覧表の下にある、全銘柄のcsvファイルのダウンロードリンクを取得する
- 上で取得したダウンロードリンクにアクセスし、csvファイルをダウンロードする
- ダウンロードしたcsvファイルを開き、記載されている基準日が本日の日付だった場合、slackに通知する
ざっとこんな感じですね。今回はFireFoxを使用していますが、Chromeを使用することもできます。
このプログラムを毎日動かすことで基準日が変化した日、つまり銘柄の構成変更があった日にslackで通知がきます。
Linuxサーバ上でダウンロードされたcsvファイルを開いてみると、以下のような感じです。
構成銘柄の情報が取得できています。
スクレイピングのコード
今回作成したPythonのコードは以下の通りです。
from bs4 import BeautifulSoup from selenium import webdriver import time import urllib.request import datetime import os import sns_post from selenium.webdriver.chrome.options import Options from selenium.webdriver.firefox.options import Options # 例外発生通知用のslack URL SLACKURL_ex = '各自のアクセストークン' # slack設定値 SLACKURL = '各自のアクセストークン' # main処理 def main(): # 日付 today = datetime.date.today().strftime('%Y%m%d') today_compare = datetime.date.today().strftime('%Y年%-m月%d日') # for Lnx header = '【HDV構成銘柄】 hdv-composition-download.py\n' sendMessage = header # スクレイピング対象URL URL = 'https://www.blackrock.com/jp/individual/ja/products/239563/ishares-core-high-dividend-etf' # スクレイピング実行 try: # ブラウザ設定 options = Options() options.add_argument('--headless') # 対象URLにアクセス driver = webdriver.Firefox(options=options) driver.get(URL) time.sleep(10) # 文字コードをUTF-8に変換し、html取得 html = driver.page_source.encode('utf-8') soup = BeautifulSoup(html, "html.parser") download_link = soup.find('div', class_='holdings fund-component-data-export').find('a', class_='icon-xls-export').get('href') download_link = URL + download_link #ここは各自の環境に合わせてパスを記載 download_path = '/home/python-code/stock-HDV/' download_filename = download_path + 'HDV_composition_' + today + '.csv' #csvファイルダウンロード urllib.request.urlretrieve(download_link, download_filename) time.sleep(20) reference_date = '' with open(download_filename, 'r',encoding='utf-8') as f: reference_date = f.readline().split(',')[1].replace('"','').replace('"','').replace('\r','').replace('\n','') # 更新されている場合、slackに投稿 if reference_date == today_compare: sendMessage += '構成銘柄が更新されています。\n基準日:' + reference_date sns_post.slackPost(SLACKURL,sendMessage) else: os.remove(download_filename) except AttributeError as e: message = "[例外発生]"+os.path.basename(__file__)+"\n"+"type:{0}".format(type(e))+"\n"+"args:{0}".format(e.args)+"\n" sns_post.slackPost(SLACKURL_ex,message) except Exception as e: message = "[例外発生]"+os.path.basename(__file__)+"\n"+"type:{0}".format(type(e))+"\n"+"args:{0}".format(e.args) sns_post.slackPost(SLACKURL_ex,message) finally: # 起動したブラウザを閉じる driver.close() driver.quit() if __name__ == '__main__': main()
プログラム中で指定しているslackのURLについては皆さんそれぞれの環境に合わせたものを入れてください。
アクセストークンの取得方法については以下記事で解説しています。
www.77-lifework.com
また、「import sns_post」の部分は自作の関数を呼び出していますので、同じような記載にして動作させるには、
上記のプログラムの他に以下のファイルも作成して配置しておく必要があります。
import slackweb import twitter # slack送信メソッド def slackPost(webhookurl,message): slack = slackweb.Slack(url = webhookurl) slack.notify(text = message) # twitter送信メソッド def twitterPost(message): # 取得したキーとアクセストークンを設定する auth = twitter.OAuth(consumer_key="wwwwwwwww", consumer_secret="xxxxxxxxxxx", token="yyyyyyyyyy", token_secret="zzzzzzzzzzz") t = twitter.Twitter(auth=auth) # メッセージを投稿する t.statuses.update(status=message)
これはTwitterへの投稿とslackへの投稿メソッドを記載しています。(Twitterの方は今回使用していませんが)
snsへのメッセージ投稿は他のプログラムからも使用するので、共通して呼び出せるよう別ファイルで記載するようにしています。
また、ダウンロードしたcsvが更新されていないものだった場合には削除するようにしています。そうしないとcsvが無限にあふれてしまうので・・・。