好きな芸能人のテレビ出演情報をLINEに通知する

#目的
好きなアイドル、お笑い芸人がテレビに出演しているのを見逃してしまうので、LINEで通知するようにしました。
<img width="258" alt="2020-05-15 (9).png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420361/e63012ab-3d3f-2aea-1ad7-00eee656eb52.png">

#概要
[Yahoo!テレビ Gガイド](https://tv.yahoo.co.jp/search/?q=%E7%9C%89%E6%9D%91%E3%81%A1%E3%81%82%E3%81%8D&g=&a=23&oa=1&s=1%22)からテレビ番組の情報を取得し、LINENotifyを使って通知を行いました。毎朝9時にRaspberrypiでプログラムを実行するように設定しました。


##番組情報取得
例えば、「眉村ちあき」の地上波の番組(地域設定東京)の場合はこのようなURLです。
https://tv.yahoo.co.jp/search/?q=眉村ちあき&g=0&a=23&oa=1&s=1

tv_information(query,romaji,jenre)という関数を定義し、入力として通知したい芸能人の名前、出演番組を記録するテキストファイル名、通知したいtv番組のジャンルを受け取ります。入力に応じたURLから情報を取得しました。今回は東京の地上波の番組に限定しています。
お笑いコンビ、ニューヨークの情報を通知したかったのですがニューヨークのワードではアメリカの州のニューヨークに関連した番組がたくさん通知されてしまうので、番組のジャンルを指定して通知できるようにしています。すべてのジャンルはjenre=0、バラエティーはgenre=5を入力します。

##LINE
[LINE Notify](https://notify-bot.line.me/ja/)
ここからトークンを取得しました。
`line_notify_token = "取得したLINE API"`のところに取得したトークンを入力します。


##使ったコード
```python:tv_line.py
import requests
from bs4 import BeautifulSoup
import sys
from time import sleep

#テレビの情報を取得する(引数: 出演者の名前、ローマ字(ファイル名にする)、ジャンル)
def tv_information(query,romaji,jenre):
#すべてのジャンルなら0、バラエティーに絞るなら5
    if jenre==0:
        no=''
    elif jenre==5:
        no='05'
    url = "https://tv.yahoo.co.jp/search/?q="+query+"&g="+no+"&a=23&oa=1&s=1" 
    res = requests.get(url)
    status = res.status_code

    #Requestsのステータスコード=! 200
    if status != 200:
        def LineNotify(message):
            line_notify_token = "取得したLINE API"
            line_notify_api = "https://notify-api.line.me/api/notify"
            payload = {"message": message}
            headers = {"Authorization": "Bearer " + line_notify_token}
            requests.post(line_notify_api, data=payload, headers=headers)
        message = "Requestsに失敗しました"
        LineNotify(message)
        sys.exit()
    

    #ステータスコード=200
    else:
        pass
    
    #検索数
    soup = BeautifulSoup(res.text,"html.parser")
    p = soup.find("p",class_="floatl pt5p")

    #検索数がで終了
    if p == None:
        print('0')
        non={}
        return non  

    
    else:
        pass
    
    answer = int(p.em.text) #検索数
    page = 1
    list1 = []  #放送日時
    list2 = []  #放送局
    list3 = []  #番組タイトル

   
    while answer > 0:
        url = "https://tv.yahoo.co.jp/search/?q="+query+"&g="+no+"&a=23&oa=1&s="+str(page)
        res = requests.get(url)
        soup = BeautifulSoup(res.text, "html.parser")

        dates = soup.find_all("div",class_="leftarea")
        for date in dates:
            d = date.text
            d = ''.join(d.splitlines())
            list1.append(d)

        for s in soup("span",class_="floatl"):
            s.decompose()
        tvs = soup.find_all("span",class_="pr35")
        for tv in tvs:
            list2.append(tv.text)

        titles = soup.find_all("div",class_="rightarea")
        for title in titles:
            t = title.a.text
            list3.append(t)

        page = page + 10
        answer = answer - 10

        sleep(3)

    #放送日時＋放送局＋番組タイトルをまとめてlist_newに
    list_new = [x +" "+ y for (x , y) in zip(list1,list2)]
    list_new = [x +" "+ y for (x , y) in zip(list_new,list3)]
    filename=romaji+'.txt'
    #テキストファイルから前回のデータを集合として展開する
    f = open(filename,'r') 
    f_old = f.read()
    list_old = f_old.splitlines()   
    set_old = set(list_old)         
    f.close()           
    
    f = open(filename, 'w') 
    for x in list_new:
        f.write(str(x)+"\n")    #ファイル書き込み
    f.close()   

    #前回のデータと今回のデータの差集合をとる
    set_new = set(list_new)
    set_dif = set_new - set_old
    return set_dif

def LINE_notify(set_dif,query,romaji):

    #差集合がなければ処理終了
    if len(set_dif) == 0:
        return  

    #差集合があればリストとして取り出してLINEに通知する
    else:
        list_now = list(set_dif)
        list_now.sort()

        for L in list_now:
            def LineNotify(message):
                line_notify_token = "取得したLINE API"
                line_notify_api = "https://notify-api.line.me/api/notify"
                payload = {"message": message}
                headers = {"Authorization": "Bearer " + line_notify_token}
                requests.post(line_notify_api, data=payload, headers=headers)
            message = query+"の出演番組情報\n\n" + L
            LineNotify(message)
            sleep(2)
        return

# すべてのジャンルの眉村ちあきの出演番組を通知
set_dif1=tv_information('眉村ちあき','mayumura',0)
LINE_notify(set_dif1,'眉村ちあき','mayumura')

# すべてのジャンルの空気階段の出演番組を通知
set_dif2=tv_information('空気階段','kuuki',0)
LINE_notify(set_dif2,'空気階段','kuuki')

# バラエティーのジャンルのニューヨークの出演番組を通知
set_dif3=tv_information('ニューヨーク','newy',5)
LINE_notify(set_dif3,'ニューヨーク','newy')

```

##実行
毎日朝9時にRaspberrypiでこのプログラムを実行するようにしました。
`crontab -e`でファイルに以下の文を書き込みました。

```
00 09 * * * python3 /home/pi/tv_line.py
```
実行時間の後にジョブを書きます。実行時間は、分、時、日、月、曜日の順で書きます。

#参考
[Yahooテレビ番組表から情報取得(Webスクレイピング初級)](https://non-programmer.com/web_scraping_yahootv01/)
[浜辺美波の出演番組をスクレイピングで取得](https://qiita.com/str416yb/items/7126625cf89909cca066)
[crontabコマンドについてまとめました 【Linuxコマンド集】]
(https://eng-entrance.com/linux-command-crontab)