Discordでニュース通知Botを作成してみた

毎週日曜日の記事更新。今回はDiscordでBotを作った話。
真面目? いいえ、ゲームの為です。

DiscordでBotを作った!

どういうBotかというと、

ゲームニュースサイトから”無料配布ゲーム”記事を通知する

というもの。

言語はPython

初めて触って結構戸惑いましたけどね….

なんとか半日で動作してよかったよかった。

仕組みとしては非常に簡単。しかも人頼り。

  1. 12:00, 18:00に自動実行する or 手動で実行する
  2. ニュースサイトのRSSを利用してニュースを取得
  3. 記事タイトルに”無料配布”の文言があるニュースを抜き出す
  4. 前回取得したニュース以前のニュースは除外
  5. Discordで抜き出し、除外されなかったニュースを指定channelにsend

ニュースサイトは、AUTOMATONさんを利用させていただきました。
ありがとうございます。


1.12:00, 18:00に自動実行する or 手動で実行する

参考:https://qiita.com/higuratu/items/033e6fa655ee4b1d2ff0

定期時刻に実行させたかったので、参考サイトを元に組む。

@tasks.loop(seconds=60)
async def loop():
    now = datetime.now().strftime('%H:%M')
    
    #12:00・18:00にニュースを自動取得する
    if now == '12:00' or now == '18:00':
        (以下、実行処理)

まず、loop関数なんてあんのかよ、しかも時間指定でなんて….

便利だな!これ!

datetimeで時間を取得して、指定した時刻かを1分置きにif文チェック。

これ、1分置きってPCに負荷はどれくらいなのか。そのうち考える。


2.ニュースサイトのRSSを利用してニュースを取得

参考:https://techacademy.jp/magazine/19148

テックアカデミーってわかりやすぃ!
これも参考サイトを元に組んでいく。

RSS_URL = 'https://automaton-media.com/feed/' #AUTOMATONのRSS-URL

#最新のニュースを取得
d = feedparser.parse(RSS_URL)

しっかりpipでインストールして、動作。

こんなにあっさりニュースを取得できるのか…..

次は目的の”無料配布ゲーム”記事のピックアップだ。


3.記事タイトルに”無料配布”の文言があるニュースを抜き出す

参考:https://note.nkmk.me/python-str-search/

もちろん参考サイト。
言語が違えば文法も違うのだ。似たのがあるのを予想してグルグル。

RSS_URL = 'https://automaton-media.com/feed/' #AUTOMATONのRSS-URL

#最新のニュースを取得
d = feedparser.parse(RSS_URL)
for entry in d.entries:

#'無料配布'の含まれるニュースタイトルをピックアップ
    if  '無料配布' in entry.title:
        no_news_flg = 0
        print(entry.title, entry.link)
        news_list.append(entry.title+ '\r\n'+ entry.link)

さっきのニュース取得コードの下部に追記。

for entry in d.entries:

取得したニュースは配列っぽいんでfor文。これはforeachに近いのかな?

if  '無料配布' in entry.title:

文字列が含まれているか、それはまさか in だけでいいとは….

複雑なことはしなくていいんすね…
構えていたのが拍子抜けですねぇ!

そこから、Discordに投げることを前提として、チャット文を整えて格納。

でも、現状古いのも拾っちゃう….

それで次!


4.前回取得したニュース以前のニュースは除外

参考:https://note.nkmk.me/python-file-io-open-with/

参考はpythonのファイル入出力について。
とりあえず、コードを。

RSS_URL = 'https://automaton-media.com/feed/' #AUTOMATONのRSS-URL

log_path = 'data/log.txt' #logファイルのパス

no_news_flg = 1 #最新ニュース有無のフラグ

#受け渡しニュースデータ用
news_list = []

#logから前回取得した最新のニュースURLを取得
with open(log_path, mode='r') as f:
    old_news_url = f.read()
    print('前回取得したニュースURL: '+ old_news_url)

#最新のニュースを取得
d = feedparser.parse(RSS_URL)
for entry in d.entries:

    #前回の最新ニュースに当たれば処理終了 (それ以降は古いニュースの為)
    if old_news_url == entry.link:
        print('最新のニュースは以上です')
        break

    #'無料配布'の含まれるニュースタイトルをピックアップ
    if  '無料配布' in entry.title:
        no_news_flg = 0
        print(entry.title, entry.link)
        news_list.append(entry.title+ '\r\n'+ entry.link)


if no_news_flg == 0:
    #最新のニュースURLに置き換える
    with open(log_path, mode='w') as f:
        f.write(d.entries[0].link)

else:
    #ニュースが無いデータを格納
    news_list.append('最新のゲーム無料配布ニュースはありません')

今までのコードに書き加える。

log_path = 'data/log.txt' #logファイルのパス

txtファイル。これに取得したニュースのURLを残して後の判定に使う。

#logから前回取得した最新のニュースURLを取得
with open(log_path, mode='r') as f:
    old_news_url = f.read()
    print('前回取得したニュースURL: '+ old_news_url)
.
.
.
    #前回の最新ニュースに当たれば処理終了 (それ以降は古いニュースの為)
    if old_news_url == entry.link:
        print('最新のニュースは以上です')
        break

取得したニュースがあるかif文チェック。
ニュースの取得順が”投稿時間の新しい順”なので、後ろに行くと古い。
なので、もし取得済と合致したら、それ以降も取得済ということ。
その地点で、ピックアップ処理を終わらせる。

if no_news_flg == 0:
    #最新のニュースURLに置き換える
    with open(log_path, mode='w') as f:
        f.write(d.entries[0].link)

else:
    #ニュースが無いデータを格納
    news_list.append('最新のゲーム無料配布ニュースはありません')

no_news_flg は”新着ピックアップニュースがあったか”というフラグ。

0なら新着あり。

1なら無し。その場合は空で配列をreturnするのは嫌なので、
無かったと文字列を格納してreturnするのです。

これ、URL更新って両パターンで必要じゃね?
動作上、差異はないけど、手間はあるよね。


5.Discordで抜き出し、除外されなかったニュースを指定channelにsend

参考:https://qiita.com/1ntegrale9/items/9d570ef8175cf178468f

締めのsend作業。

@tasks.loop(seconds=60)
async def loop():
    now = datetime.now().strftime('%H:%M')
    
    #12:00・18:00にニュースを自動取得する
    if now == '12:00' or now == '18:00':
        channel = client.get_channel(NEWS_CHANNEL_ID) #発言チャンネルを指定
        news_list = rss_picker() #ニュースを取得

        #ニュースをチャットに送信
        for news in news_list:
            await channel.send(news)

今までのコードは実は関数だったのだ。
rss_picker() がそれ。

それから配列に格納された文字列を取得。
foreachのようなもので引き出してチャット送信。

これがこの機能。

コンソール画面。

しっかり動作しているか確認するためにとりあえず表示で確認。

いいっすね。


半日でなんとか形に。

結構面白かった。もっと作りたいですね….

MinaSnooze
  • MinaSnooze
  • 割と多趣味な社会人。
    アニメ作品だとワールドウィッチーズシリーズが大好き。
    モータースポーツにも興味があるが、今のところF1が一番好き。
    音楽や音楽ゲームも大好きで、様々な音楽ゲームに触れたいと思う日々。

2件のコメント

  • さすがです!

    • ありがとうございます!
      これからも精進します!

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)