2017年5月14日日曜日

【電算機】2017年度 横浜Fマリノス 試合日程 を自動取得

年明けぐらいから、ちょこちょこやっていた、試合日程の自動取得がやっとできた (´Д`)
もう、いまさら、って時期だけども。
python (with Beautiful Soap 4)でFマリノスのHPをクロール・スクレイピング、
試合日程をCSVファイルに吐き出して、
Googleカレンダーに読み込みます。

CSVの 読み込み時の注意としては、
・カレンダー種類が選べる様になっているので、ちゃんと選べ
・日時が同じだと上書きになる模様  時間が違うと別の予定(追加)になる模様
・日程・時刻が未定のやつは、とりあえず登録したけど、
 確定してから登録し直す必要あり。
 予定を消せないのでちょっとメンドい。
 ので、とりあえず testカレンダーに取り込んでおいた。
 ★CSVだと、既存予定を削除したりできない。
 ical形式だとイケるのかなぁ…。
 時刻未定のとか、後で上書き更新したいじゃん。(´・ε・`)

※ 以下のコード表示は、syntac2html にて作成。便利。いいね。
 インラインCSSにしておけば、BloggerのHTML編集でコピペできるんだぜー

import urllib.request
from bs4 import BeautifulSoup
import csv
import codecs
from datetime import datetime as dt
from datetime import timedelta


html = urllib.request.urlopen('http://www.f-marinos.com/schedule/match/allMatch/2017')
print('fm get status: ',html.status)

soup = BeautifulSoup(html, 'html.parser')

# 日程表(match schedule)を取得(Tagにしておく)
matchSchedule = (soup.findAll('table', class_='matchSchedule'))[0]

# カテゴリ
category = matchSchedule.findAll('td', class_='category')
# マッチナンバー
matchNum = matchSchedule.findAll('td', class_='matchNumber')
# チーム
team = matchSchedule.findAll('td', class_='team')
# 日時(開催日、キックオフ時間)
date = matchSchedule.findAll('td', class_='date')
# 開催地(ステジアム、ホーム/アウェイ)
stadium = matchSchedule.findAll('td', class_='stadium')

# 一覧表示してみる
for (c,m,d,t,s) in zip(category,matchNum,date,team,stadium):
    wd = d.findAll('p')
    ws = d.findAll('p')
    print(c.text.strip(),
            m.text.strip(),
            wd[0].text.strip(),
            wd[1].text.strip(),
            t.text.strip(),
            ws[0].text.strip(),
            ws[1].text.strip())


print('CSV出力するよ')

with codecs.open('./fm_schedule.csv', 'w', encoding='utf-8') as f:
    header = [
        'Subject',
        'Start Date',
        'Start Time',
        'End Date',
        'End Time',
        'All Day Event',
        'Location',
        'Private'
    ]

    writer = csv.DictWriter(f, fieldnames=header)
    writer.writeheader()

    for (c, m, d, t, s) in zip(category, matchNum, date, team, stadium):

        wd = d.find_all('p')
        ws = s.find_all('p')

        # カテゴリー+節+相手チーム+(H/A)
        # ToDo:”明治安田”を削除する
        sj = c.text.strip() + ' ' + m.text.strip() + ' ' + t.text.strip() + ' '
        # "明治安田J1"を"J1"に短くするよ
        sj = sj.replace("明治安田", "")
        # ホーム・アウェイ情報を試合名称のお尻に付与する
        if ws[0].text.strip() in 'HOME':
            sj += '(H)'
        else:
            sj += '(A)'

        # ゲーム開催日時
        w_day = '2017/' + (wd[0].text.strip())[:-3]
        w_time = wd[1].text.strip()

        # 5/10〜5/11みたいな書き方になっている場合は、5/10にしてしまう
        if w_day in '〜': w_day = (w_day.split('('))[0]

        # 開始時刻が未定ならば、All Day Eventとする
        if w_time in '未定':
            ade = 'True'
            w_time = '00:00'    # 仮時刻
        else:
            ade = 'False'

        # 日時をdatetimeオブジェクトに変換、様式がダメならスキップする
        try:
            w_start = dt.strptime(w_day+' '+w_time, '%Y/%m/%d %H:%M')
            if ade == 'False':
                w_end = w_start + timedelta(minutes=120)
                w_start_time = w_start.strftime('%H:%M')
                w_end_time = w_end.strftime('%H:%M')
            else:
                w_start_time = '00:00'
                w_end_time = '00:00'
        except ValueError:
            print('ERROR: '+sj+':'+w_day)
            continue

        # 一行書き込み
        writer.writerow(
        {
            'Subject': sj,
            'Start Date': w_day,
            'Start Time': w_start_time,
            'End Date': w_day,
            'End Time': w_end_time,
            'All Day Event': ade,
            'Location': ws[1].text.strip(),
            'Private': 'True'
        }
        )

0 件のコメント: