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

毎週日曜日の記事更新。今回はDiscordでBotを作った話。
真面目? いいえ、ゲームの為です。
DiscordでBotを作った!
どういうBotかというと、
ゲームニュースサイトから”無料配布ゲーム”記事を通知する
というもの。
言語はPython。
初めて触って結構戸惑いましたけどね….
なんとか半日で動作してよかったよかった。
仕組みとしては非常に簡単。しかも人頼り。
- 12:00, 18:00に自動実行する or 手動で実行する
- ニュースサイトのRSSを利用してニュースを取得
- 記事タイトルに”無料配布”の文言があるニュースを抜き出す
- 前回取得したニュース以前のニュースは除外
- Discordで抜き出し、除外されなかったニュースを指定channelにsend
ニュースサイトは、AUTOMATONさんを利用させていただきました。
ありがとうございます。
1.12:00, 18:00に自動実行する or 手動で実行する
参考:https://qiita.com/higuratu/items/033e6fa655ee4b1d2ff0
定期時刻に実行させたかったので、参考サイトを元に組む。
1 2 3 4 5 6 7 |
@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
テックアカデミーってわかりやすぃ!
これも参考サイトを元に組んでいく。
1 2 3 4 |
RSS_URL = 'https://automaton-media.com/feed/' #AUTOMATONのRSS-URL #最新のニュースを取得 d = feedparser.parse(RSS_URL) |
しっかりpipでインストールして、動作。
こんなにあっさりニュースを取得できるのか…..
次は目的の”無料配布ゲーム”記事のピックアップだ。
3.記事タイトルに”無料配布”の文言があるニュースを抜き出す
参考:https://note.nkmk.me/python-str-search/
もちろん参考サイト。
言語が違えば文法も違うのだ。似たのがあるのを予想してグルグル。
1 2 3 4 5 6 7 8 9 10 11 |
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) |
さっきのニュース取得コードの下部に追記。
1 |
for entry in d.entries: |
取得したニュースは配列っぽいんでfor文。これはforeachに近いのかな?
1 |
if '無料配布' in entry.title: |
文字列が含まれているか、それはまさか in だけでいいとは….
複雑なことはしなくていいんすね…
構えていたのが拍子抜けですねぇ!
そこから、Discordに投げることを前提として、チャット文を整えて格納。
でも、現状古いのも拾っちゃう….
それで次!
4.前回取得したニュース以前のニュースは除外
参考:https://note.nkmk.me/python-file-io-open-with/
参考はpythonのファイル入出力について。
とりあえず、コードを。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
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('最新のゲーム無料配布ニュースはありません') |
今までのコードに書き加える。
1 |
log_path = 'data/log.txt' #logファイルのパス |
txtファイル。これに取得したニュースのURLを残して後の判定に使う。
1 2 3 4 5 6 7 8 9 10 11 |
#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文チェック。
ニュースの取得順が”投稿時間の新しい順”なので、後ろに行くと古い。
なので、もし取得済と合致したら、それ以降も取得済ということ。
その地点で、ピックアップ処理を終わらせる。
1 2 3 4 5 6 7 8 |
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作業。
1 2 3 4 5 6 7 8 9 10 11 12 |
@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のようなもので引き出してチャット送信。
これがこの機能。

コンソール画面。
しっかり動作しているか確認するためにとりあえず表示で確認。
いいっすね。
半日でなんとか形に。
結構面白かった。もっと作りたいですね….
さすがです!
ありがとうございます!
これからも精進します!