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
定期時刻に実行させたかったので、参考サイトを元に組む。
@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のようなもので引き出してチャット送信。
これがこの機能。
コンソール画面。
しっかり動作しているか確認するためにとりあえず表示で確認。
いいっすね。
半日でなんとか形に。
結構面白かった。もっと作りたいですね….
さすがです!
ありがとうございます!
これからも精進します!