Webスクレイピングで急落銘柄通知ツールを作成してみた
どうも、こじまるです。
以前Twitterの仲良しさんと投資ツールについてやり取りしていた時に、下記のようなツールを使ってみたいという話がありました。
そのため、当月・翌月が権利確定月の銘柄で、急落銘柄を通知するツールを作ってみようと思いました。
Webスクレイピングで急落銘柄通知ツールの作成
要件定義
処理の流れ
今回使用するプログラムは、権利確定日の情報を取得する事前処理と定期的に急落銘柄を判定し通知するメイン処理に分離しました。
事前処理
権利確定日の情報は、頻繁に変更されるものではありません。そのため、スクレイピング先のサーバの負荷を考慮し、一ヶ月に一度あるいは一度だけ実行されればいいと思います。
メイン処理(定期実行)
メイン処理に関しては、当月・翌月が権利確定日の銘柄で、急落銘柄を通知する必要があります。急落銘柄は、前日終値と現在の株価から割合を求めます。タイムリーにその情報を得るためにも定期的な実行が必要になります。
事前処理
①権利確定日の銘柄情報を取得
権利確定日の銘柄情報取得のために、https://kabuoji3.com/を使用しました。https://kabuoji3.com/robots.txtを確認しましたが、Allow:/と記載されていますので、問題なく使用できそうです。
User-Agent: * Allow:/ Sitemap:http://kabuoji3.com/sitemap/sitemap-index.xml
今回使用するURLは、https://kabuoji3.com/stockholder/{銘柄コード}/になります。こちらのURLにブラウザでアクセスすると、権利確定月が表示されています。
こちらの権利確定月の表示をXPATHで参照するようにし、取得しました。
url = "https://kabuoji3.com/stockholder/{}/".format(stock_code) headers = {"User-Agent": "Chrome"} html = requests.get(url, headers=headers) html.raise_for_status() dom_tree = lxml.html.fromstring(html.content) # 権利確定月 vesting_date = dom_tree.xpath('//*[@id="base_box"]/div/div[3]/dl[2]/dd/text()') if not len(vesting_date): continue stock_vesting_date = vesting_date[0]
②銘柄情報の保存
権利確定月の情報は日々更新されるわけではないので、下記のようにExcelデータとして保存し、それをメイン処理で読み取む形で利用します。
メイン処理
②銘柄情報を取得
事前処理で取得した権利確定月の情報を利用して、当月・翌月が権利確定月の銘柄のみに対してのみ、スクレイピング処理を行います。
当月・翌月が権利確定月の銘柄の判定
取得した権利確定月の情報には月を指す文字以外の余計な文字も含まれています。正規表現を使って、必要となる月を示す文字列のみを取得しています。
# 当月・翌月の文字列を取得 dt_now = datetime.now() tmp = dt_now + relativedelta(months=1) dt_month = str(dt_now.month) dt_next_month = str(tmp.month) ... stock_vesting_date = str(row[2]) # 権利確定月 if stock_vesting_date == "随時": # 随時は対象外に continue else: month_list = re.findall("\d+月",stock_vesting_date) vesting_month_list = [s.replace("月","") for s in month_list] # 当月・翌月が権利確定月の銘柄のみ後段の処理を実行 if dt_month in vesting_month_list or dt_next_month in vesting_month_list: pass else: continue
急落銘柄の判定
現在の株価、前日終値は以前の記事と同様に、みん株のサイトからウェブスクレイピングを利用して取得します。詳細に関しては、下記の記事を見てください。
cojimaru-chan.hatenablog.com
取得した株価と前日終値を利用し、急落率を計算します。ユーザが定義した急落率を超えた場合に、リストに情報を保持するように実装しました。
# 現在値 tmp = chart_dom_tree.xpath('//*[@id="layout"]/div[2]/div[3]/div[2]/div/div[1]/div/div/div[1]/div[2]/div/div[2]/div/text()') current_price = float(re.sub(r'\D','',tmp[0])) # 前日終値 stock_previous_closing_place = parse_dom_tree(chart_dom_tree,'//*[@id="contents"]/div[3]/div[1]/div/div/div[2]/div/div[1]//tr[1]/td[1]','円','') price_drop_rate = (1 - current_price / stock_previous_closing_place) * 100 if price_drop_rate >= TARGET_DROP_RATE: output_list.append([stock_code,stock_name,current_price,stock_previous_closing_place,price_drop_rate])
③急落銘柄を通知
Slackへの通知には、Incoming Webhooksを利用して実行しています。詳細はこちらでは割愛しますので、必要であれば、下記記事を参考にしてください。
参考
https://developers.wonderpla.net/entry/2020/06/18/110005
コード
今回使用したコードを下記にアップロードしました。興味がありましたら、事前処理はdataCollection.py、メイン処理はcreateStockMap.pyを確認してください。
github.com
実行結果
急落率 : 5%の条件で実行してみました。急落率が5%以上の銘柄が取得できています。
他のサイトで急落率を確認しましたが、一致していますね。