ビジネスパーソン・ガジェット置場 empty lot for business

営業や仕事、それに伴う生活を便利に楽にするツール、ガジェットを作ります。既にあるツールも自分用にカスタマイズ。

Yahooファイナンス情報を毎日自動で取得し上司に自動でメール(報告)する 【python + BeautifulSoup】

今回の設定はーーー上司よりYahooファイナンスから上位50社のデータを毎日取得してメールで報告すること、また日々の変化を記録するために取引値のデータのみを別ファイルに転記しておくこと、の二つを指示され、毎日手動でやるのは面倒くさいなと感じた担当者が自動でデータの取得、報告、保存までを行うことにした!という感じです。

f:id:kslabo51:20220219213836j:plain

Yahooファイナンスのデータを定期的に自動で取得してまとめる

定期実行でサイトにあるテーブルデータを毎日自動的に取得、メール送信するガジェットになります。

  • 取得したデータを整形しデータ日付をファイル名としcsv形式でフォルダに保存
  • 日々の変化を見るため取引値のみ抜き出し、別途ファイルに記録
  • データがまとまったら折れ線グラフで可視化(まとまってから)
  • 整形したデータをメールに添付し上司に報告する

※データの取得と整形、メールの送信は今回別々のプログラムファイルにしております。

 

ガジェットイメージ図

f:id:kslabo51:20220221203608p:plain

必要な設定

■データ: 値上がり率:株式/株価ランキング - Yahoo!ファイナンス

■プログラム言語:Python

■ライブラリ:requests, bs4, pandas, datetime, datetime, os, shutil, json,  smtplib, MIMEText, formatdate, MIMEMultipart, MIMEApplication

■その他:

  • Automater(mac)
  • Editor(Atom or Jupyterlab or VScord など)
  • Gmailをアプリケーションで実行する際に使用する設定
  • カレンダー(mac)
  • ファイルは2種類(デイリーファイル、取引値を更新するファイル)
  • デイリーファイルを一旦格納するフォルダと報告が済んだものを移すフォルダ

 

手順① 日々の変化を見るようのファイルを用意

f:id:kslabo51:20220220120825p:plain

※Yahooで検索可能な情報なので会社名を消さずに載せていることはご容赦ください。

※デイリーファイルは下記のコードを実行すると自動で作成されます。

 

手順② サイトにある情報を定期に取得する

コードは下記になります。今回はBeautifulSoupというもので一つずつデータを整形しております。

from bs4 import BeautifulSoup
import requests
import pandas as pd
import datetime as dt


def main():
    url = 'https://finance.yahoo.co.jp/stocks/ranking/up'

    # データ取得
    res = requests.get(url)
    soup = BeautifulSoup(res.text, 'html.parser')

    # サイト内のテーブルを見つける
    table = soup.find('table')
    elem_tbody = table.find('tbody')

    # テーブルからデータを抽出しデータフレームに格納
    df = pd.DataFrame()
    today = dt.date.today()
    for i, elem_tr in enumerate(elem_tbody.find_all('tr')):
        _df = {}
        elems_td = elem_tr.find_all('td')
        _df['企業名'] = elems_td[0].find('a').text
        elems_li = elems_td[0].find_all('li')
        _df['コード'] = int(elems_li[0].text)
        _df['市場'] = elems_li[1].text
        _df['取引値'] = int(float(elems_td[1].find_all('span')[0].text.replace(',', '')))
        _df['取引日']  = today.strftime('%Y/%m%/%d')
        _df['前日比']  = int(float(elems_td[2].find_all('span')[0].text.split('+')[1]))
        _df['前日比(%)']  = float(elems_td[2].find_all('span')[3].text.split('+')[1].split('%')[0])
        _df['出来高']  = int(''.join(elems_td[3].text.split('株')[0].replace(',', '')))
        _df = pd.DataFrame(_df, index=[i])
        df = pd.concat([df, _df])

    # 抽出したデータを一旦デイリーで保存
    check_date = today.strftime('%m_%d')
    df.to_csv(f'daily/{check_date}.csv', index=False)

    # 積み上げ用データファイルを読み込み
    summary = pd.read_csv('master.csv')

    # 今回のデータでsummaryにない企業がないかチェック
    add_companies = df['企業名'][~df['企業名'].isin(summary['企業名'])]
    # summaryにない企業があった場合は、その列をsummaryに追加しておく
    for company in add_companies:
        # 仮のリスト作成
        d = [0]*(summary.shape[1]-1)
        # リストの先頭にsummaryにない企業名のリストを追加
        d.insert(0, company)
        summary.loc[summary.shape[0]] = d

    # summaryに今回取得したデータのうち「取引値」をマージ
    summary = pd.merge(summary, df[['企業名', '取引値']], on='企業名', how='left')

    # 列名を日付に変更
    day = today.strftime('%m/%d')
    summary = summary.rename(columns={'取引値': day})

    # summaryをエクスポートし上書き
    summary.to_csv('master.csv', index=False)
    

if __name__ == '__main__':
    main()

注)2/21データを取得するサイトの表記が変わったためコード変更しております

 

デイリーファイルは下記のようになりました。

f:id:kslabo51:20220220120454p:plain

 

こちらは、送信前データが入るフォルダに日付付きのフォルダ名で格納されます。

f:id:kslabo51:20220220122327p:plain

 

 

また、日々の変化を見るための取引値ファイルは下記のように日付とデータが入りました。

f:id:kslabo51:20220220121304p:plain

こちらのファイルは毎日データを取得のたびに列が追加されていきます。

手順③ 取得したデータを添付して上司にメールで報告する

 

Gmailをアプリケーションで実行する際に使用する設定をまずは行います。それについてはこちらをご覧ください。

 

以下、実行コードになります。添付するデータはデイリーファイルにしております。

# メース設定(メール送信のアドレスとパスワードをjsonファイルから呼び出し)
from glob import glob
import os
import shutil
import json
import smtplib
from email.mime.text import MIMEText
from email.utils import formatdate
from datetime import date
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication

# ファイルの移動関数
def move_file(filepath):
    shutil.move(filepath, 'send_file')
    
def main():
    
    with open('secret.json', 'r') as f:
        address_password = json.load(f)
    
    from_addr = address_password['ADDRESS']
    password = address_password['PASSWORD']
    
    subject = 'ファイナンス情報デイリー報告'
    body = '部長\n\n昨日のファイナンス情報をお送りいたします。添付ご確認をお願い申し上げます。\n\n Anon'
    to_addr = '上司のメアド'
    
    smtpobj = smtplib.SMTP('smtp.gmail.com', 587)
    smtpobj.starttls()
    smtpobj.login(from_addr, password)
    
    # 添付ありの設定
    msg = MIMEMultipart()
    msg['Subject'] = subject
    msg['From'] = from_addr
    msg['To'] = to_addr
    msg['Date'] = formatdate()
    msg.attach(MIMEText(body))
    
    file_path = glob('daily/*.csv')
    filename = file_path[0]
    filepath = os.path.basename(filename)
    
    file = open(filename, 'rb')
    with open(filename, "rb") as f:
        attachment_file = MIMEApplication(f.read())
    attachment_file.add_header('Content-Disposition', 'attachment', filename=filepath)
    msg.attach(attachment_file)
    
    # 下記は添付なしの場合
    # msg = MIMEText(body)
    # msg['Subject'] = subject
    # msg['From'] = from_addr
    # msg['To'] = to_addr
    # msg['Date'] = formatdate()
    
    smtpobj.send_message(msg)
    smtpobj.close()
    
    move_file(filename)
    
    
if __name__ == '__main__':
    main()   

上記を実行するとメールが走ります。そして、添付したファイルは報告済みファイルとしてフォルダ移動されます。

f:id:kslabo51:20220220123103p:plain

 

手順④ 定期実行の設定を行う。

macであればautomaterとカレンダーで定期実行を設定します。実行方法はこちらから

arachnes-web.hatenablog.jp

 

これで、毎日自動でデータを取得、ファイルを整形、上司への報告を行ってくれます!

楽ちん楽ちん!

 

参考サイト

いまにゅさんの動画がわかりやすくて最高です!

【超本格的】Pythonで業務自動化を学びたい人がまず見るべき動画|定期実行の仕組み構築までをわかりやすく解説 - YouTube