LoginSignup
1
0

More than 3 years have passed since last update.

バスケ(Bリーグ)のデータをサーバレスに取得する

Posted at

昔、ゆるふわに始めるバスケの分析でやったものを、もう少し発展させてデータを取得し、GCPのStorageに保存できるまでをcloud functionsを使って実装しました。

構成

今回はスポナビのBOXスコアを1試合ずつ取得して、tsvファイルにしてStorageに保存します。
そのため、cloud functionsのpython3.7でトリガーをHTTPにしました。
HTTPトリガーのパラメータに試合日や試合番号を指定することで特定の試合結果を取得します。

フォルダ構成は以下のようにしました。

gcf_bleague_boxscore
├── main.py
└── requirements.txt

実装

pythonのBeautifulSoupでデータを取得し、取得したいデータを整形します。
cloud functionsの実行環境では/tmpを一時領域として使うことができるため、そこを利用してtsvファイルを作成しています。

main.py
import pandas as pd
from bs4 import BeautifulSoup
import urllib.request
import re
from google.cloud import storage

def bleaue_boxscore(request):
    request_json = request.get_json()

    # 基本情報の設定
    if request_json and 'target_date' in request_json:
        TARGET_DATE = request_json['target_date']
    else:
        TARGET_DATE = '19900101'
    if request_json and 'target_game' in request_json:
        TARGET_GAME = request_json['target_game']
    else:
        TARGET_GAME = '3269'
    if request_json and 'div' in request_json:
        DIV = request_json['div']
    else:
        DIV = 'b1'
    URL_TOP = 'https://sportsnavi.ht.kyodo-d.jp/basketball/stats/'+DIV+'/score/'+TARGET_GAME+'/'
    URL_BOXSCORE =  URL_TOP+'box/'
    OUTPUT_FILENAME = 'boxscore_P'+TARGET_DATE+TARGET_GAME+'.tsv'

    # チーム名の取得
    html = urllib.request.urlopen(URL_TOP)
    top = BeautifulSoup(html, 'html5lib')
    team = top.find_all('div', class_='name')
    home_name = team[0].text.translate(str.maketrans({' ': '', '\n': ''}))
    away_name = team[1].text.translate(str.maketrans({' ': '', '\n': ''}))

    # 試合情報の取得(日付,tipoff,試合会場,節,カテゴリ) 
    loc = top.find('div', class_='note').string
    section = top.section.h1.string
    game_date = re.match(r'[0-9]{4}年[0-9]{1,2}月[0-9]{1,2}日' , loc).group()
    tipoff_time = re.search(r'[0-9]{1,2}:[0-9]{1,2}' , loc).group()
    arena = re.sub(r'.*試合会場:', '' , loc)
    sec = re.search(r'第[0-9]{1,2}節', section).group().translate(str.maketrans({'第': '', '節': ''}))
    div = re.match(r'B[0-9]{1}', section).group()

    # それぞれのボックススコアを取得
    tables_home = pd.read_html(URL_BOXSCORE + 'h/', flavor='bs4')
    tables_away = pd.read_html(URL_BOXSCORE + 'a/', flavor='bs4')

    # ボックススコアに情報を追加
    boxscore_home = tables_home[1].dropna(subset=['#']).assign(
                                        team=home_name,
                                        game_date=game_date,
                                        tipoff_time=tipoff_time,
                                        arena=arena,
                                        sec=sec,
                                        div=div)
    boxscore_away = tables_away[1].dropna(subset=['#']).assign(
                                        team=away_name,
                                        game_date=game_date,
                                        tipoff_time=tipoff_time,
                                        arena=arena,
                                        sec=sec,
                                        div=div)
    boxscore = pd.concat([boxscore_home, boxscore_away],ignore_index=True)

    boxscore.to_csv('/tmp/'+OUTPUT_FILENAME, sep='\t' ,header=False, index=False)

    # storageにファイルをアップロード
    storage_client = storage.Client()
    bucket = storage_client.get_bucket('ストレージのバケット名')
    blob = bucket.blob('data/'+OUTPUT_FILENAME)
    blob.upload_from_filename('/tmp/'+OUTPUT_FILENAME)

    return f'functions finished.'+OUTPUT_FILENAME
requirements.txt
google-cloud-storage
bs4
html5lib
pandas

以下のコマンドでデプロイします。

gcloud beta functions deploy bleaue_boxscore --trigger-http --runtime=python37

使ってみた感じ

デプロイが完了するとAPIのURLが払い出されるのでリクエストパラメータに試合情報を入力してPOSTすることで、データの取得が可能になります。

curl -X POST https://[リージョン]ー[プロジェクト名]cloudfunctions.net/bleaue_boxscore -H "Content-Type:application/json" --data '{"target_date":"20190421","target_game":"3525","div":"b1"}'

img01.png

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0