見出し画像

LINE自動送信プログラムを作った

こんにちは。springrollです。
まずはじめに少し謝罪をさせてください。
今回始めてブログのような形で自分が作成したプログラムを公開するので、コードに丁寧にコメントアウトをしようと思ったのですがやはり高校生という立場上、学業を並行して行わなければならないためにあまりプログラミングに関しての時間を捻出できませんでした。そのため、今回公開させて頂くコードには、
皆様が利用する際に最低限変更を加えてほしい箇所
にしかコメントアウトを行っていません。マナーとして、コメントはしっかりと書くべきなのは承知の上ですが、このまま記事の投稿を先延ばしにしても自信を持って皆様にお見せできるようなコードを書くことは難しいと感じたため、見るに耐えないようなコードではあると思いますが、今回投稿させていただくことにしました。どのようなご指摘でも真摯に向き合うつもりですので是非アドバイスのほどよろしくお願いします。

さて、この記事では前回の投稿で少し触れた「LINE自動送信プログラム」について深彫りしていきたいと思います。

コード

コードの全貌です。

import requests
from bs4 import BeautifulSoup
import urllib
import json
import datetime


class App:
    def __init__(self, city):
        self.URL_YAHOO = "https://www.yahoo.co.jp/"
        self.TOKEN_LINE = "your line token"  # Please replace it with your LINE notify token.
        self.API_LINE = "https://notify-api.line.me/api/notify"
        self.TOKEN_WEATHER = "your openweather map token"  # Please replace it with your Open Weather Map token.
        self.API_WEATHER = "https://api.openweathermap.org/data/2.5/weather?q={}&appid={}&lang=ja&units=metric".format(city, self.TOKEN_WEATHER)
        self.TOKEN_NOTION = "your notion token"  # Please replace it with your Notion integration token.
        self.NOTION_DATABASE_ID_WEEKLY = "your notion weekly tasks database token"  # Please replace it with your oneday tasks database id.
        self.NOTION_DATABASE_ID_ONEDAY = "your notion oneday tasks database token"  # Please replace it with your weekly tasks database id. 
        self.NOTION_DATABASE_URL_WEEKLY = f'https://api.notion.com/v1/databases/{self.NOTION_DATABASE_ID_WEEKLY}/query'
        self.NOTION_DATABASE_URL_ONEDAY = f"https://api.notion.com/v1/databases/{self.NOTION_DATABASE_ID_ONEDAY}/query"
        self.list_title = []
        self.list_url = []
        self.item_name = []
        self.item_tag = []
        self.message_yahoo = ""
        self.message_weather = ""
        self.message_notion = ""
        self.dt = datetime.datetime.now()
        self.dt_adjust = self.dt + datetime.timedelta(hours=9)
        self.today_year = self.dt_adjust.year
        self.today_date = self.dt_adjust.date()
        self.today_hour = self.dt_adjust.hour
        self.today_day = self.today_date.weekday()

    def index_app(self):
        self.get_notion_data()
        self.get_weather()
        self.scraping_yahoo()
        self.send_to_line("\n{}({})\n\nToday's Schedules&Tasks:{}\n\nWeather{}\n\nRecentry NEWS{}".format(self.today_date, self.today_date.strftime("%a"), self.message_notion, self.message_weather, self.message_yahoo))


    def scraping_yahoo(self):
        self.html = requests.get(self.URL_YAHOO)
        self.soup = BeautifulSoup(self.html.content, "html.parser")

        self.topic = self.soup.find(id="tabpanelTopics1")
        for i in self.topic.find_all("a"):
            self.list_title.append(i.text)
            self.get_news_url = i.get("href")
            self.show_news_url = urllib.parse.urljoin(self.URL_YAHOO, self.get_news_url)
            self.list_url.append(self.show_news_url)
            self.message_yahoo += "\n{}\n{}".format(i.text, self.show_news_url)
        
    def get_weather(self):
        self.jsondata = requests.get(self.API_WEATHER).json()
        self.message_weather += "\ncity:{}".format(self.jsondata["name"])
        self.message_weather += "\ntemp:{}".format(self.jsondata["main"]["temp"])
        self.message_weather += "\nweather:{}".format(self.jsondata["weather"][0]["description"])

    def get_notion_data(self):
        self.headers_notion = {'Authorization': f'Bearer {self.TOKEN_NOTION}',
          'Notion-Version': '2021-08-16',
          'Content-Type': 'application/json'}

        self.payload_notion = {'page_size': 20}

        self.response = requests.post(self.NOTION_DATABASE_URL_WEEKLY, data=json.dumps(self.payload_notion), headers=self.headers_notion).json()
        self.result = self.response["results"]

        for i in range(len(self.result)):
            if self.result[i]["properties"]["day"]["number"] == self.today_day or self.result[i]["properties"]["day"]["number"] == 7:
                self.message_notion += "\n{}".format(self.result[i]['properties']['Name']['title'][0]['plain_text'])

        self.response = requests.post(self.NOTION_DATABASE_URL_ONEDAY, data=json.dumps(self.payload_notion), headers=self.headers_notion).json()
        self.result = self.response["results"]
        
        for i in range(len(self.result)):
            if self.result[i]["properties"]["Date"]["date"]["start"] == str(self.today_date):
                self.message_notion += "\n{}".format(self.result[i]["properties"]["Name"]["title"][0]["plain_text"])

        if self.message_notion == "":
            self.message_notion += "\nNothing."

    def send_to_line(self, msg):
        self.headers_line = {"Authorization": f"Bearer {self.TOKEN_LINE}"}
        self.payload_line = {"message": f"message: {msg}"}
        requests.post(self.API_LINE, headers=self.headers_line, data=self.payload_line)


if __name__ == "__main__":
    place = "your city, your country"  # Please replace it with your living city ex:"Sendai, JP"
    app = App(place)
    app.index_app()

初心者にしては、それなりに簡潔にまとめられたのではないかと思います。
また、GitHub上でもソースコードを公開しております。

概要説明

Yahoo!ニュースのスクレイピング

コードでは以下にあたります。

# 以下41行目
    def scraping_yahoo(self):
        self.html = requests.get(self.URL_YAHOO)
        self.soup = BeautifulSoup(self.html.content, "html.parser")

        self.topic = self.soup.find(id="tabpanelTopics1")
        for i in self.topic.find_all("a"):
            self.list_title.append(i.text)
            self.get_news_url = i.get("href")
            self.show_news_url = urllib.parse.urljoin(self.URL_YAHOO, self.get_news_url)
            self.list_url.append(self.show_news_url)
            self.message_yahoo += "\n{}\n{}".format(i.text, self.show_news_url)
  1. requests.get(yahooホームページのURL) でhtmlファイルを取得

  2. id指定でYahooホームページのトピックニュースを選択

  3. ニュースのタイトル、URLをforループで1つ1つ取得

  4. LINEメッセージとして送るため、変数にタイトルとURLを代入

大体このような流れです。

現在の天気の取得

コードでは以下にあたります。

# 以下53行目
    def get_weather(self):
        self.jsondata = requests.get(self.API_WEATHER).json()
        self.message_weather += "\ncity:{}".format(self.jsondata["name"])
        self.message_weather += "\ntemp:{}".format(self.jsondata["main"]["temp"])
        self.message_weather += "\nweather:{}".format(self.jsondata["weather"][0]["description"])
  1. JSONデータを取得

  2. 地名、気温、天気状況を取得したデータから抽出

なお、取得するデータの地域はどこで設定しているかというと

# 以下89行目
if __name__ == "__main__":
    place = "your city, your country"  # Please replace it with your living city ex:"Sendai, JP"
    app = App(place)
    app.index_app()

このplace変数で指定しています。

Notionタスク取得

コードでは以下にあたります。

#以下59行目
    def get_notion_data(self):
        self.headers_notion = {'Authorization': f'Bearer {self.TOKEN_NOTION}',
          'Notion-Version': '2021-08-16',
          'Content-Type': 'application/json'}

        self.payload_notion = {'page_size': 20}

        self.response = requests.post(self.NOTION_DATABASE_URL_WEEKLY, data=json.dumps(self.payload_notion), headers=self.headers_notion).json()
        self.result = self.response["results"]

        for i in range(len(self.result)):
            if self.result[i]["properties"]["day"]["number"] == self.today_day or self.result[i]["properties"]["day"]["number"] == 7:
                self.message_notion += "\n{}".format(self.result[i]['properties']['Name']['title'][0]['plain_text'])

        self.response = requests.post(self.NOTION_DATABASE_URL_ONEDAY, data=json.dumps(self.payload_notion), headers=self.headers_notion).json()
        self.result = self.response["results"]
        
        for i in range(len(self.result)):
            if self.result[i]["properties"]["Date"]["date"]["start"] == str(self.today_date):
                self.message_notion += "\n{}".format(self.result[i]["properties"]["Name"]["title"][0]["plain_text"])

        if self.message_notion == "":
            self.message_notion += "\nNothing."

    def send_to_line(self, msg):
        self.headers_line = {"Authorization": f"Bearer {self.TOKEN_LINE}"}
        self.payload_line = {"message": f"message: {msg}"}
        requests.post(self.API_LINE, headers=self.headers_line, data=self.payload_line)
  1. 色々とやって指定したデータベースのデータを取得する。

  2. そのデータの中からデータベース内で設定した日付と今日の日付(週間タスクの場合データベースの数値プロパティの数値と曜日を表す数値)があっていればそのデータのタイトルを取得

  3. LINEメッセージ変数に代入

  4. データベース内からなんのデータも得られなかった場合は、LINEメッセージ変数に”Notiong”を代入。

正直、ここは自分もよく理解できていないです。
以下、参考にさせていただいたページのURLを貼っておきます。
PythonでNotionのAPIを操作する方法 (qlitre-weblog.com)

プログラム利用にあたって

このプログラムを利用するためにいくつか行っていただきたいことがあります。以下で説明します。

環境構築

このプログラムでは

  • requests

  • BeautifulSoup

以上2つの外部モジュールを使用しています。未インストールの方はインストールをお願いします。いずれもpipコマンドでインストール可能です。

Notion内で行ってほしいこと

このプログラムではNotionのデータベースに記載されている情報をタスクとして送信しています。その際、今日の日付とデータベース内で指定した日付が適合するか調べるなど、プロパティが重要になってきます。
ですので、プロパティの名前は以下の通りに統一していただけると幸いです。逆に、ご自身のデータベースのプロパティに合わせてソースコードの編集をしていただくのも良いと思います。

1日限定タスク

1日限定タスクは、

  • Name (Type:title)

  • Date (Type:Date)

以下の2つは必要となりますので、プロパティ名も含め、上と同じようにしてください。

週間タスク

週間タスクは

  • Name (Type:title)

  • day (Type:Number)

以下の2つは必要となりますので、プロパティ名も含め、上と同じようにしてください。
また、週間タスクの曜日の指定は上の画像の通り

  • 月曜日= 0 ~ 日曜日 = 6

  • 毎日=7

のようにしてください。

コード内で変更してほしい箇所

このプログラムでは

の3つを必要とします。また、それにともなってソースコード内で変更していただきたい箇所は以下のコメントで示されているところです。

# 以下ソースコード9行目
    def __init__(self, city):
        self.URL_YAHOO = "https://www.yahoo.co.jp/"
        self.TOKEN_LINE = "your line token"  # 取得したLINEアクセストークンに置換してください。
        self.API_LINE = "https://notify-api.line.me/api/notify"
        self.TOKEN_WEATHER = "your openweather map token"  # 取得したOpen Weather Mapアクセストークンに置換してください。.
        self.API_WEATHER = "https://api.openweathermap.org/data/2.5/weather?q={}&appid={}&lang=ja&units=metric".format(city, self.TOKEN_WEATHER)
        self.TOKEN_NOTION = "your notion token"  # 取得したNotionインテグレーションに置換してください。
        self.NOTION_DATABASE_ID_WEEKLY = "your notion weekly tasks database token"  # 作成した1日用タスクデータベースのidを入力してください。
        self.NOTION_DATABASE_ID_ONEDAY = "your notion oneday tasks database token"  # 作成した週間タスクデータベースのidを入力してください。
        self.NOTION_DATABASE_URL_WEEKLY = f'https://api.notion.com/v1/databases/{self.NOTION_DATABASE_ID_WEEKLY}/query'
        self.NOTION_DATABASE_URL_ONEDAY = f"https://api.notion.com/v1/databases/{self.NOTION_DATABASE_ID_ONEDAY}/query"

また、以下、天気情報の地域の指定も行ってください。

#以下ソースコード89行目
if __name__ == "__main__":
    place = "your city, your country"  # Please replace it with your living city ex:"Sendai, JP"
    app = App(place)
    app.index_app()

定期実行について

私はこのプログラムを定期実行で毎朝6時に送信されるようにしています。
定期実行の方法としてはGitHub Actionsを使っています。
説明は今回は省略させていただきますが、参考にさせていただいたYouTube動画のリンクを貼り付けておきます。

あとがき

このようにしっかりと自分が作成したプログラムを文にまとめるのは初めてだったので色々ミスが多いと思いますが、もし見つけた際はぜひコメントなどで教えていただけると幸いです。
割と急いで書いたのですがそれでも2時間はかかってしまいました。学業優先で動くとどうしてもnoteにはあまり時間を割けられないと思うので、正直低浮上になる可能性が高いです。
でも、できるだけ時間を見つけて書いていきたいと思いますので是非
「スキ」をお願いします!

この記事が気に入ったらサポートをしてみませんか?