1. kozakura16

    Posted

    kozakura16
Changes in title
+Webスクレイピング×IFFFTでプロ野球の試合結果をLINE通知する(1/2)
Changes in tags
Changes in body
Source | HTML | Preview
@@ -0,0 +1,157 @@
+### はじめに
+今回はWebスクレイピングとIFFFTを用いてプロ野球の試合結果をLINE通知するようにしてみる。筆者はプロ野球の中でもDeNAファンなので、DeNAの試合結果を通知することにする。Webスクレイピングに前から興味があったし、今まで試合結果はYahoo!開いて、スポーツ開いて、プロ野球開いて、、といった感じで手順が多くて面倒だったので、「じゃあLINE通知されたらいいんじゃね?」と思ったのがきっかけ。
+
+### IFFFTとは?
+IFTTTとはIF This Then Thatの略称で「あることが起きたら、あることをする」ことができる外部アプリ連携サービスである。本サイトは[こちら](https://ifttt.com/discover)をどうぞ。
+例えば、本サービスを使えば「天気予報サービスで雨予報が起きたら、LINEに通知する」といったことが可能になる。
+サイトの登録方法については[こちら](https://www.atmarkit.co.jp/ait/articles/1711/22/news031.html)をどうぞ。
+また、ThisについてWebhookにより作ることが可能(Thenも可能らしい)で、今回はこれを利用する。
+
+### Webスクレイピングとは?
+Webから情報をスクレイピング(抽出)することを意味する。具体的には、Webページ上のhtml構文を解析して、好きな情報を取得することができる。例えば、複数の2ちゃんねるのサイトから特定ジャンルのタイトルのスレッドのリンクのみを抽出して、自分専用のまとめページを作ったりなんかができる。
+
+### 全体構成
+全体構成はこんな感じ。IFTTT的に表現すると「DeNAの試合が終わったら、結果をLINEに通知する」ということになる。
+①DeNAの公式サイトの試合結果を監視
+②試合結果が終了になったことを検知
+③IFTTTのWebhookに試合結果を通知
+④Webhookの検出(Thisの部分)
+⑤LINEに試合結果を通知(Thatの部分)
+![図1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431401/ca8c861a-5a3c-6deb-a26a-d8e2dc6df7ff.jpeg)
+
+### 実装
+#### Webスクレイピングにより、DeNAの試合結果が終了になることを検出
+pythonのpyqueryを用いて、DeNAの公式サイトのページを取得する。ソースコードは以下の通り。
+ざっくりと説明すると、以下のような感じ。
+1. 30分に一度公式サイトの試合結果ページを見に行く
+ URLの末尾2桁は01~05のいずれかが設定されるのだが法則がわからずのため、すべてを見に行って、ページがあるときに次の処理に進むようにした。
+2. 試合終了の場合に、結果を取得する
+ 試合終了を表すhtmlの属性を取得して、"終"の文字がある場合は試合終了とみなし、結果(スコア、先攻後攻など)を取りに行く。
+3. 取得した試合結果をIFTTTのWebhookに通知する
+ 2.で取得した試合結果をIFTTTのWebhookに必要な値(LINE通知した文字列)を詰めてPOSTする。Webhookの詳細については後ほど記事を書くことにする。
+
+```
+
+# -*- coding:utf-8 -*-
+import requests
+from datetime import datetime
+import urllib
+import json
+import time
+import sys
+import os
+from pyquery import PyQuery as pq
+from pathlib import Path
+
+def main():
+ while True:
+ today = datetime.now()
+ date = today.strftime('%Y%m%d')
+ flag_bat_first = False
+
+ if os.path.isfile('./log/' + date): # ファイルがあるか確認あれば終了
+ print(date + ' file is exist...')
+ time.sleep(60 * 30)
+ continue
+
+ flag_page_found = False
+ for i in range(5):
+ print(date)
+ url = 'https://www.baystars.co.jp/game/result/' + date + '0' + str(i+1)
+ print('url: '+url )
+ query = pq(requests.get(url).content)
+ print('query: ' +query(".tag").text() )
+
+ # Webページが取得できるか確認
+ search_result = query(".focNavy01b").text()
+ query_tag = query(".tag").text()
+ if search_result == "":
+ print("page found!!")
+ flag_page_found = True
+ break
+
+ if flag_page_found == False:
+ print("cannot get web page...")
+ time.sleep(60 * 30)
+ continue
+
+
+ flag_game_over = False
+ for text in query_tag:
+ print('text: ' + text)
+ if text == "終":
+ flag_game_over = True
+
+ if flag_game_over == False:
+ print("the game is not stared or playing...")
+ time.sleep(60 * 30)
+ continue
+
+
+ # 先攻後攻の判定
+ print("-------GAME TEAM--------")
+ team_names = query(".game--score-left").text()
+ if team_names.split('\n').index('横浜DeNA') == 0:
+ print("DeNA is bat first!")
+ flag_bat_first = True
+ else:
+ print("DeNA is not bat first!")
+ flag_bat_first = False
+
+ # 試合結果の取得
+ print("-------GAME RESULT--------")
+ game_result = query(".game--score-right").text()
+ game_score = game_result.split('\n')
+ print("bat_first: " + game_score[1])
+ print("bat_not_first: " + game_score[2])
+
+ if flag_bat_first == True: # DeNAが先攻の場合
+ dena_score = int(game_score[1])
+ opponent_score = int(game_score[2])
+ else:
+ dena_score = int(game_score[2])
+ opponent_score = int(game_score[1])
+
+ result_text = ""
+ if dena_score > opponent_score:
+ print("DeNA won!")
+ result_text = "won!"
+ elif dena_score < opponent_score:
+ print("DeNA lose...")
+ result_text = "lost..."
+ else:
+ result_text = "Draw"
+ print("Draw\n")
+
+ result_text = result_text + url
+ print(game_result)
+
+ # IFTTTのWebHookに試合結果を通知
+ URL = "https://maker.ifttt.com/trigger/dena_result/with/key/dnWNxgJh1uE-JUEPaIIkCw"
+ METHOD = "POST"
+ HEADERS = {"Content-Type" : "application/json"}
+
+ # PythonオブジェクトをJSONに変換する
+ obj = {"value1" : game_score[1], "value2" : game_score[2], "value3" : result_text}
+ json_data = json.dumps(obj).encode("utf-8")
+
+ # httpリクエストを準備してPOST
+ request = urllib.request.Request(URL, data=json_data, method=METHOD, headers=HEADERS)
+ with urllib.request.urlopen(request) as response:
+ response_body = response.read().decode("utf-8")
+ print(response_body)
+
+ # logファイルを作成する
+ Path('./log/' + date).touch()
+
+
+ print(date + ' logged!')
+
+
+
+if __name__=='__main__':
+ main()
+```
+
+#### 続く
+続きが書けたらこちらにリンクを貼ります!