PythonとLINE Notifyを利用して競馬情報を自動送信してみた

# 1. はじめに

最近バックエンドエンジニアに転職した「だい」です。
エンジニア転職する前日に、Pyhtonを用いて何かやってみたいなと思っていたところ、父親からJRA（日本中央競馬会）の公式サイトに当週のレースの歴史を紹介する欄があり、それがなかなか面白いという話を聞いたので、所定の時間になったら自身のLINEに自動で取得してくれるコードを書いてみました。
趣味でやったものなので、いろいろ突っ込みあるかと思いますが温かい目でみていただけると嬉しいです。

# 2. 簡単な設計

どんな要件があるかを考えて、以下の順序で進めていくことにしました。 1日で作りたかったので機能は極限まで省いています。

1. スクレイピングのことよく分からないので簡単な本を読む(これは設計ではないですが)
* JRAのHPから該当の情報を取得する
* 父親が簡単に確認できるようにLINEで通知を送る→LINE norifyを利用する
* 当日のメインレースが2つ以上ある場合はどちらも送信する
* 毎週、土曜日と日曜日の午前9時に自動で送信する

お客さんからの注文でもないので要件をざっくりまとめただけです。

# 3. 実装開始

* 簡単な本を読む

実装開始と言いつつ何もわからないので下記の本を読みました。

「スクレイピング・ハッキング・ラボ　Pythonで自動化する未来型生活」
www.amazon.co.jp/dp/B08H1KBYG2

たしか3分の1ぐらい読み進めて、自分のやりたいことはできそうだなって思い終了しました。いつか全部読み切りたいです。

この段階で必要なものになりそうなライブラリーをインストール。
Pythonのバージョンは3.6でvenv内にインストールしました。

```
$ pip install requests
$ pip install BeautifulSoup4
``` 
* JRAから情報を取ってくる処理を記載

```python:jra_raceinfo.py
import requests
from bs4 import BeautifulSoup as bs
from datetime import datetime

#情報取得先のURLに日付が含まれているため当日の情報を取得
raceday = datetime.now()
year = raceday.strftime("%Y")
week_day = raceday.strftime("%m%d")

def race_info(args):
    #取得先のURLを代入
    url = "https://www.jra.go.jp/keiba/thisweek/" + year + "/" + week_day + "_{}".format(args) + "/race.html"

    res = requests.get(url)
    soup = bs(res.content, "html.parser")
    #レース名を取得する
    title_unit = soup.find("div", attrs={"id": "race_title"})
    title_name = title_unit.find("img").get("alt")
    #レースの歴史を取得する
    history_div = soup.find("div", attrs={"class": "contents_unit"})
    race_history = history_div.find("p").get_text()
    return title_name, race_history

```

次にLINE Notifyを利用するためのAPIを取得します。
これは本の範囲外だったので、youtubeでキノコードさんの動画を参考にしながら作りました。この有料級の動画が無料なんて本当に大変感謝しています。
https://www.youtube.com/watch?v=FuCJd0ftVsU




```python:lineapi.py
import requests
from datetime import datetime
from jra_horse_info import race_info #さっき作ったやつ

#最高3レースだからとりあえずループの範囲はいったんこれで。
#1〜2レースしか無いとき用に例外処理入れる。
for num in range(1, 4):
    try:
        title_name, race_history = race_info(num)
        time = datetime.now()
        #取得したトークン認証情報を入力
        TOKEN = 'トークン'
        #LINE公式に記載のline notifyのapiurl
        api_url = 'https://notify-api.line.me/api/notify'
        send_contents = title_name + "\n" + race_history

        TOKEN_dic = {'Authorization': 'Bearer' + ' ' + TOKEN}
        send_dic = {'message': send_contents}

        requests.post(api_url, headers=TOKEN_dic, data=send_dic)
    except:
        pass
```

実装最後の部分としてcronで自動実行するようにしました。
本当はcronだけで動かしたかったのですが、venvでやったために何かがうまくいかず(何だったか忘れてしまいました)シェルスクリプトを作る→それをcronで動かす、という形を取りました。
以下のサイトを参考にしていました。
■cron
https://qiita.com/katsukii/items/d5f90a6e4592d1414f99
■シェルスクリプト
https://qiita.com/zayarwinttun/items/0dae4cb66d8f4bd2a337

```shell:exe.sh
#! /bin/zsh

cd /Users/ユーザー名/venv_scraping
source bin/activate
cd /Users/ユーザー名/scraping/keiba_LINE/
#普通に実行するだけなら以下のコマンドだけで十分なはず。
/Users/ユーザー名/venv_scraping/bin/python lineapi.py
deactivate
cd /Users/ユーザー名

```

```
$ crontab -e

#コマンドの実行によってcrontabの編集ができるので処理時間とシェルの実行を記載
0 9 * * 6,7 source /Users/ユーザー名/scraping/keiba_LINE/exe.sh >> /Users/ユーザー名/scraping/keiba_LINE/cron.log 2>&1
```

これで無事に所定の時間にJRAのサイトから取ってきた情報を父とのLINEのグループに送れるようになりました！

# 4. さいごに
スクレイピングの仕方とLINEAPIの利用についての書きたかったものなのでコード自体はあまり参考にしない方が良いです。もっと良い書き方あります。
是非ご自身の興味あるサイトを対象にしていろいろ試してみてください！