ここ数日間はある思いつきでプログラムを書いていました。

普段はTwitterなどのSNSをやっていない代わりにDiscordのプライベートなチャットルームで延々と発言しているのですが、ただのチャットにとどまらず何か活用したいと思っていました。 具体的にはWebhookをDiscordに通知することで気軽にデスクトップ通知が使えるので、何かしらの通知にはもってこいというわけです。 そこで、Discord活用の第一弾としてGigazineのヘッドラインニュースを自動で通知してくれるプログラムを書きました。 Botと書きたいところですが、発言内容をもとに動かすわけではなく毎日実行するタスクなので若干説明が厄介です。

技術的な説明はポートフォリオを作る予定なのでそちらに書くとしてここでは大まかな作業の流れと、苦労したところなどについて書いておくつもりです。

初日 (7月7日)

もともとはGigazineだけではなく、自宅サーバーの通知等の諸々の作業をまとめて作る予定でした。 プラグイン形式にでもしようかなと思ったのですが、最初から壮大な計画を立てるとうまくいかないことが多いのでまずはフィードを拾ってくる作業から始めました。 Gigazineのヘッドラインはある程度体裁は決まっているものの、ブログの本文に散りばめてあるリンクを拾わなければなりません。 普段はNode.jsのCheerioというライブラリとBullというライブラリを組み合わせて作るのですが、いつも同じプログラムでは代わり映えがしないのでJavaScriptベースではなくPythonを使うことにしました。 また今回使うCeleryはBullよりもWebのUIを自分で作る必要はなかったので、このプログラムもなるべく時間をかけずに作るつもりでした。

HTMLのパーサーは定番のBeautifulSoupを利用しました。 ただし、普段使っているCheerioやDOMベースの操作とそこまで違わないものの独自な箇所もあるため最初はかなり手こずりました。 最初はあらかじめダウンロードしたファイルからカテゴリを抽出してDiscordのWebhookに送信まで終わらせました。

2日目 (7月8日)

DiscordのEmbedタイプを利用して個々のリンクを表示できるようにしました。 このEmbedタイプは調べるとOpenGraphの表示に使われているもので、テキストの表示だけでなく画像の表示など柔軟に使えることを知りました。 そこで、GigazineのページだけでなくSeleniumを利用して各リンク先のスクリーンショットを保存することも考えました。 実際にリンク先へ飛んでスクリーンショットを取るスクリプトも用意することはできたのですが、いざ保存してみるとページ内の広告も多く、Discordの限られたスペースに表示するのはあまり意味がないことに気づきました。 せっかく作ったのと、過去のヘッドラインを調べるのに後々このスクリプトは再流用するかもしれません。 また、保存した画像をアップロードするのにGyazoのアカウントも取得しました。 Linuxでも使えるのですが、バイナリのみの提供はなくリポジトリを登録するのに抵抗があったためWindowsでアカウントを取得しました。 今ではコマンド経由でアップロード可能です。

スクリーンショットの代わりにOpenGraphで提供されている画像を使うことにしました。 ただ新たに浮上した問題点としてはサイトによっては相対URLで画像を提供されてあったり、スクレイピング時に文字化けしているサイトもちらほらあったのでその修正をしました。 その他諸々の対応をしましたが、この時点では手元でコマンドを実行すればDiscordにWebhookを送信するまでは実現しました。

3日目 (7月9日)

Celeryで動かすようにスクリプトをリファクタリングしつつ、プログラム全体もある程度まとまりました。 いままでPythonで複数ファイルを使うプロジェクトは初めてだったのでディレクトリ構成も気を使いつつ、pytestなどの単体テストも徐々に書き始めました。 このプロジェクトは1日くらいで簡単に作れるものだと思っていましたが、新しいツールを覚えたり、ライブラリの選定もあったりしたので案外時間がかかりました。 また、DockerでCronを動かすのも大変だと思っていました。 このサイトを操作しているAPIはRailsで書いていますが、そこでもCronを使って予約投稿の仕組みを実現するはずだったのですが現時点ではまだうまくいってません。 若干Cronの使い方は自信がなかったのですが、案外むずかしくありませんでした。 また、Cronをいつ実行するかのタイミングなども最初はCronで常に回してBashで制御する予定でしたがCrontabで制御しました。 全体的な改良も加えながら進めました。 実際に動かしてみるとdescriptionのメタタグがないサイトがあって失敗したり、PDFのみのリンクでスクレイピングに失敗するなどのトラブルもありましたが比較的早い段階でイレギュラーっぽいリンクが多くあったため後々に修正するよりもすばやく対応できました。

それで、Docker経由で自宅サーバーにデプロイして今に至ります。 今回はビジュアル的なフィードバックがわかりやすかったのでReact等を書くのとはまた違った新鮮さと、面白さがありあっという間でした。 Pythonと新しいライブラリを多数使えたことは自分にとっても収穫でした。 明日はこのプログラムを拡張してBot化するか、あるいはアーカイブ向けのサイトを作るか考えていますが、ひとまずはGitHubで公開できればいいなと思っています。