【Python】経済指標カレンダーを個人のGoogle Calendarに追加する

FX投資
この記事は約21分で読めます。

以前の投稿でYahooファイナンスから経済指標カレンダーの情報をスクレイピングで取得しましたが、その内容を自分のGoogle Calendarに追加して、重要な指標を忘れないようにしたいと思います。
過去に投稿した以下2つの記事の合わせ技になります。
【Python】スクレイピングで経済指標カレンダー情報を取得する
PythonとGoogle Calendar APIを使ってGoogle Calendarの予定を取得・追加する

スポンサーリンク

経済指標カレンダー情報を取得

まずはYahooファイナンスから以下の記事に記載した方法で、経済指標カレンダー情報を取得します。
【Python】スクレイピングで経済指標カレンダー情報を取得する

取得コードは以下になります。

# -*- coding: utf-8 -*-
import requests
from bs4 import BeautifulSoup
from datetime import datetime, timedelta
import pandas as pd

def get_priority(td_):
    if len(td_.find_all('span', class_ = 'icoRating1')) > 0:
        priority = 1
    elif len(td_.find_all('span', class_ = 'icoRating2')) > 0:
        priority = 2
    elif len(td_.find_all('span', class_ = 'icoRating3')) > 0:
        priority = 3
    else:
        priority = 0
    return priority

def get_country(td_):
    if len(td_.find_all('span', class_ = 'icon18 icoUsa18')) > 0:
        country = 'アメリカ'
    elif len(td_.find_all('span', class_ = 'icon18 icoJpn18')) > 0:
        country = '日本'
    elif len(td_.find_all('span', class_ = 'icon18 icoCnh18')) > 0:
        country = '中国'
    elif len(td_.find_all('span', class_ = 'icon18 icoSui18')) > 0:
        country = 'スイス'
    elif len(td_.find_all('span', class_ = 'icon18 icoFra18')) > 0:
        country = 'フランス'
    elif len(td_.find_all('span', class_ = 'icon18 icoEu18')) > 0:
        country = 'EU'
    elif len(td_.find_all('span', class_ = 'icon18 icoGbr18')) > 0:
        country = 'イギリス'
    elif len(td_.find_all('span', class_ = 'icon18 icoGer18')) > 0:
        country = 'ドイツ'
    elif len(td_.find_all('span', class_ = 'icon18 icoRsa18')) > 0:
        country = '南アフリカ'
    elif len(td_.find_all('span', class_ = 'icon18 icoAus18')) > 0:
        country = 'オーストラリア'
    elif len(td_.find_all('span', class_ = 'icon18 icoCan18')) > 0:
        country = 'カナダ'
    elif len(td_.find_all('span', class_ = 'icon18 icoNzl18')) > 0:
        country = 'ニュージーランド'
    elif len(td_.find_all('span', class_ = 'icon18 icoHkg18')) > 0:
        country = '香港'
    elif len(td_.find_all('span', class_ = 'icon18 icoSin18')) > 0:
        country = 'シンガポール'
    else:
        country = 0    
    return country

def get_weeklycalendar(date):
    url = 'https://info.finance.yahoo.co.jp/fx/marketcalendar/?d={}'.format(date)
    soup = BeautifulSoup(requests.get(url).content,'html.parser')
    div_bodybottom = soup.find_all('div', id = 'contents-body-bottom')
    tr = div_bodybottom[0].find_all('tr')
    data = []
    year = int(date[:4])
    for i in range(1,len(tr)):
        th = tr[i].find_all('th')
        td = tr[i].find_all('td')
        if len(th) > 0:
            date_, weekday = th[0].text.split(' ')
            if date_ == '1/1':
                year += 1
        if len(td) > 0:
            tempdata = []
            tempdata.append(year)
            tempdata.append(date_)
            tempdata.extend([d.text for d in td])
            tempdata.append(get_priority(td[2]))
            tempdata.append(get_country(td[1]))
            data.append(tempdata)
    header = ['年','日付', '時刻', '経済指標', 'blank', '前回(修正)', '予想', '結果', '重要度','国']
    df = pd.DataFrame(data, columns = header)
    df = df.drop('blank', axis = 1)
    return df

def get_datetime(df_):
    dt = []
    for i in range(df_.shape[0]):
        year = df_.iloc[i,df_.columns.get_loc('年')]
        month, day = df_.iloc[i,df_.columns.get_loc('日付')].split('/')
        time = df_.iloc[i,df_.columns.get_loc('時刻')]
        if time == '未定':
            hour, minute = 0,0
        else:
            hour, minute = df_.iloc[i,df_.columns.get_loc('時刻')].split(':') 
        year, month, day, hour, minute = int(year), int(month), int(day), int(hour), int(minute)

        if hour > 23:
            tempdate = datetime(year, month, day)
            tempdate = tempdate + timedelta(days = 1)
            hour = hour - 24
            dt.append(datetime(tempdate.year, tempdate.month, tempdate.day, hour, minute))
        else:
            dt.append(datetime(year, month, day, hour, minute))
    return dt

date = '20190831'
dfs = []
for i in range(5):
    print(date)
    dfs.append(get_weeklycalendar(date))
    date_ = datetime.strptime(date, '%Y%m%d')
    date_ = date_ - timedelta(days = 7)
    date = datetime.strftime(date_, '%Y%m%d')
    
df = pd.concat(dfs).reset_index(drop = True)
df['datetime'] = get_datetime(df)
df = df.sort_values('datetime').reset_index(drop = True)

データフレーム(df)の中身を表示すると以下の結果が得られているはずです。

Google Calendar用の辞書データに変換する

先程得られたデータフレーム(df)をGoogle Calendarに追加するために、以下のような辞書形式(json形式)に変換していきます。
各パラメータ(summary, description等)の意味は下記リンクの過去投稿を御覧ください。
PythonとGoogle Calendar APIを使ってGoogle Calendarの予定を取得・追加する

event = {
      'summary': '予定1',
      'location': 'Shibuya Office',
      'description': 'サンプルの予定',
      'start': {
        'dateTime': '2019-09-10T09:00:00',
        'timeZone': 'Japan',
      },
      'end': {
        'dateTime': '2019-09-10T17:00:00',
        'timeZone': 'Japan',
      },
    }

国別のデータフレームの作成

まず全ての国の経済指標をGoogle Calendarに表示すると訳がわからなくなりそうなので、国別のデータフレームを作成します。

df_Jpn = df[df['国'] == '日本']
df_Usa = df[df['国'] == 'アメリカ']
df_Cnh = df[df['国'] == '中国']
df_Sui = df[df['国'] == 'スイス']
df_Fra = df[df['国'] == 'フランス']
df_Eu = df[df['国'] == 'EU']
df_Gbr = df[df['国'] == 'イギリス']
df_Ger = df[df['国'] == 'ドイツ']
df_Rsa = df[df['国'] == '南アフリカ']
df_Aus = df[df['国'] == 'オーストラリア']
df_Can = df[df['国'] == 'カナダ']
df_Nzl = df[df['国'] == 'ニュージーランド']
df_Hkg = df[df['国'] == '香港']
df_Sin = df[df['国'] == 'シンガポール']

Google Calendar用のデータフレームの作成

ここからは日本の経済指標カレンダーのデータフレーム(df_Jpn)だけを扱います。
df_JpnをGoogle Calendarで使用する辞書形式に変換しやすいデータフレーム(df_event_Jpn)に変換します。
以下のコードになります。

df_event_Jpn = pd.DataFrame()
df_event_Jpn['summary'] = df_Jpn['経済指標']
df_event_Jpn['start'] = [{'dateTime':str(i.date())+'T'+str(i.time()),'timeZone':'Japan'} for i in df_Jpn['datetime']]
df_event_Jpn['end'] = [{'dateTime':str(i.date())+'T'+str((i+timedelta(minutes=5)).time()),'timeZone':'Japan'} for i in df_Jpn['datetime']]
df_event_Jpn['location'] = df_Jpn['国']
df_event_Jpn['description'] = ['前回(修正):{} 予想:{} 結果:{}'.format(r[4],r[5],r[6]) for i,r in df_Jpn.iterrows()]
df_event_Jpn['重要度'] = df_Jpn['重要度']

やっていることは、
summaryにイベントの内容を記述したいので、経済指標の列の追加。
start, endにはdateTimeとTimeZoneの2つの情報を辞書形式で入れ子構造で追加。end時間はstart時間の5分後としている。
locationには一応国名を追加。(なくても大丈夫です。)
descriptionに前回(修正)、予想、結果の情報を追加。
重要度は後ほどGoogle Calendar上で分けようと思うので重要度列に追加。

df_event_Jpnを表示すると以下データフレームが得られているはずです。

辞書形式への変換およびpickle保存

重要度別にGoogle Calendarに追加しようと思うので、重要度で分けて辞書形式にします。
to_dict()という関数を使っています。

event_Jpn_imp1 = [d[:-1].to_dict() for i,d in df_event_Jpn.iterrows() if d['重要度'] == 1]
event_Jpn_imp2 = [d[:-1].to_dict() for i,d in df_event_Jpn.iterrows() if d['重要度'] == 2]
event_Jpn_imp3 = [d[:-1].to_dict() for i,d in df_event_Jpn.iterrows() if d['重要度'] == 3]

event_Jpn_imp3を表示すると以下のような内容になっていると思います。

[{'summary': '4-6月期 四半期実質国内総生産(GDP、速報値) [年率換算]',
  'start': {'dateTime': '2019-08-09T08:50:00', 'timeZone': 'Japan'},
  'end': {'dateTime': '2019-08-09T08:55:00', 'timeZone': 'Japan'},
  'location': '日本',
  'description': '前回(修正):2.2%(2.8%) 予想:0.4% 結果:1.8%'},
 {'summary': '4-6月期 四半期実質国内総生産(GDP、速報値) [前期比]',
  'start': {'dateTime': '2019-08-09T08:50:00', 'timeZone': 'Japan'},
  'end': {'dateTime': '2019-08-09T08:55:00', 'timeZone': 'Japan'},
  'location': '日本',
  'description': '前回(修正):0.6%(0.7%) 予想:0.1% 結果:0.4%'},
 {'summary': '7月 全国消費者物価指数(CPI、生鮮食料品・エネルギー除く) [前年同月比]',
  'start': {'dateTime': '2019-08-23T08:30:00', 'timeZone': 'Japan'},
  'end': {'dateTime': '2019-08-23T08:35:00', 'timeZone': 'Japan'},
  'location': '日本',
...

これをpickleで保存します。ここからは重要度3の指標だけ扱います。

import pickle
with open('event_Jpn_imp3.json', mode='wb') as f:
    pickle.dump(event_Jpn_imp3, f)

Google Calendarに経済指標カレンダー予定を追加

Google Calendarにpythonで予定を追加するには、色々と準備が必要です。
何度も書いていますが、その準備は過去投稿を御覧ください。
PythonとGoogle Calendar APIを使ってGoogle Calendarの予定を取得・追加する

過去投稿で書いたinsert_event.pyのコードを以下のように書き換えます。

from __future__ import print_function
import datetime
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request

# If modifying these scopes, delete the file token.pickle.
# SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']
SCOPES = ['https://www.googleapis.com/auth/calendar']

def main():
    creds = None
    # The file token.pickle stores the user's access and refresh tokens, and is
    # created automatically when the authorization flow completes for the first
    # time.
    if os.path.exists('token.pickle'):
        with open('token.pickle', 'rb') as token:
            creds = pickle.load(token)
    # If there are no (valid) credentials available, let the user log in.
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
        else:
            flow = InstalledAppFlow.from_client_secrets_file(
                'credentials.json', SCOPES)
            creds = flow.run_local_server(port=0)
        # Save the credentials for the next run
        with open('token.pickle', 'wb') as token:
            pickle.dump(creds, token)

    service = build('calendar', 'v3', credentials=creds)

    # event = {
    #   'summary': '予定1',
    #   'location': 'Shibuya Office',
    #   'description': 'サンプルの予定',
    #   'start': {
    #     'dateTime': '2019-09-10T09:00:00',
    #     'timeZone': 'Japan',
    #   },
    #   'end': {
    #     'dateTime': '2019-09-10T17:00:00',
    #     'timeZone': 'Japan',
    #   },
    # }
    #
    # event = service.events().insert(calendarId='コピーしたIDを貼り付け',
    #                                 body=event).execute()

    with open('event_Jpn_imp3.json', mode='rb') as f:
        events = pickle.load(f)

    for e in events:
        event = service.events().insert(calendarId='自分が追加したいカレンダーID',
                                    body=e).execute()

if __name__ == '__main__':
    main()

変更点がわかりやすいように以前に記述していた箇所はコメントアウトにしています。

35〜47行目で設定していたeventの代わりに、先程pickle保存していたevent_Jpn_imp3.jsonをeventsとしてloadします。
このeventsにはたくさんのeventデータが入っているので、for文で順番にGoogle Calendarに追加していきます。それが55〜57行目の部分です。

これをターミナルで実行します。

$ python insert_event.py

Google Calendarに移動して8月の予定表に、以下のように予定が追加されていればうまくいっています。

おすすめプログラミング勉強サイト

Pythonのプログラミングの勉強をしたいという方には「udemy」というサイトがおすすめです。
動画と実際のプログラムを書きながら解説してくれるので非常にわかりやすいです。
また、教材も豊富でプログラミングだけでなく、ビジネススキルやブログサイト作成の教材などもあるので是非みてみてください。

以上で終わりです。
もし参考になった場合はポチッとしておいていただけるとうれしいです。

 にほんブログ村 IT技術ブログへ

コメント

タイトルとURLをコピーしました