reTerminalで収集したテキストを常時wordcloud画像化して表示するデバイスを作成

f:id:ueponx:20220209235510p:plain

先日、NGK2022Sという名古屋合同懇親会という名のIT系コミュニティの合同新年会のLT大会が開催されました。

note.com

そのイベントの中で以下のような内容のLTを行いました。

f:id:ueponx:20220209235322p:plain

一応、コロナ禍で名ばかりのSeeedJP UGのメンバーにはなっているのですが、SeeedさんreTerminalのことについて紹介しました。 LTの中ではちょっと思いついたネタを紹介してみたのですが、折角なのでそのネタを実際に作ってみようかなと思い今回のエントリに至ります。

そのネタはこんなものになります。

Node-REDでのリアルタイムTweetのwordcloud画像作成し、reTerminalの画面に表示する

f:id:ueponx:20220211142055j:plain

詳しくは以下に書いていきます。

最後にもまとめていますが、このデバイスは本当にNode-REDと相性のよいデバイスだなと思います。

今回の手順

作ろうとするものの大まかな手順としては以下の様になると思います。

  • Node-REDのインストール
  • wordcloudモジュール(およびコマンド)のインストール
  • テスト用テキストのダウンロード(alice.txt)(これはやらなくてもよい)
  • alice.txtを使用してwordcloud画像を作成する(これはやらなくてもよい)
  • 日本語フォントを取得する
  • Node-RED拡張機能をインストールする(TwitterkuromojiDashBoradimage-outputbase64cron
  • フローを作成する
  • 実行する

では順を追って簡単に説明していきたいと思います。細かくは別のエントリにしてもいいのかも。

Node-REDのインストール

これはNode-REDを使用している人からは見慣れた手順となります。このコマンドではNode-REDをインストールするためにNode.jsの比較的新しいバージョンがインストールされます。また、古いバージョンのNode-REDをインストールしている場合にはバージョンアップも行われるので、バージョンの縛りがある方は注意が必要です。

$ bash <(curl -sL https://raw.githubusercontent.com/node-red/linux-installers/master/deb/update-nodejs-and-nodered)

あとは、Node-REDの起動はサービス化してもいいと思いますが、簡単にするならCLInode-redと起動すればOKです。デフォルトではセキュリティが問題ありですのでパスワードの設定は行うようにしてください。今回は説明は省略しています。

wordcloudモジュール(およびコマンド)のインストール

wordcloudモジュールはテキストから頻度に応じて文字を大きく表示してくれるという見える化のできる機能を提供するものになります。今回はNode-REDからこの機能を提供してくれるものを探していたのですが、簡単に作るものがなかなか見当たらなかったので今回はコマンドラインツール(wordclo_cli)をexecノードから使用することにしました。Node-REDから実行できるとなお良かったと思いますが、今回は手軽さを求めたのでこちらの方法にしています。

参考(wordcloudモジュールのインストール)

uepon.hatenadiary.com

インストールに関しては以下のコマンドを実行すればよいのですが…

$ pip3 install wordcloud

上記コマンドの実行でインストール処理は完了するのですが、そのままではnumpyモジュールのバージョンに関するエラーが発生し、wordcloud_cliのコマンドも実行できません。そこで、関係ありそうなモジュールの再インストールを行おうと以下のように実行してみますが、それでもうまくいきません。

$ pip3 install numpy
$ pip3 install pillow
$ pip3 install wordcloud

これは、バージョンの問題になるようなので、そのままインストールしても、想定より古いモジュールが既にインストールされていますというメッセージが表示されます。

RuntimeError: module compiled against API version 0xe but this version of numpy is 0xd

そこで、以下のようにしてオプションスイッチを追加して、強制的にnumpyモジュールのバージョンアップを行います。

$ pip3 install numpy --upgrade --ignore-installed

これでモジュールのインストールもwordcloud_cliのコマンド実行できるようになります。ただ、インストール先のディレクトリはユーザのホームディレクトリにインストールされ、そのパスは~/.local/bin/wordcloud_cliとなっているのでこちらをパス指定して実行してください。解析用のテキストとしてalice.txtを使用したので、それを取得してからwordcloud画像を生成してみます。

$ wget https://raw.githubusercontent.com/amueller/word_cloud/master/examples/alice.txt
$ ~/.local/bin/wordcloud_cli --text alice.txt --width 640 --height 480 --imagefile wordcloud.png

alice.txtのwordcloud画像

f:id:ueponx:20220210000931p:plain

日本語フォントを取得する

先程はアルファベットの文章を使っていたので、システムフォントを使えばよかったのですが、今回はTwitterのツイートの文字情報を使用しているので、表示されるテキストも自ずと日本語になります。以前はWindows環境で開発をしていたのでフォントもメイリオなどのWindowsフォントで良かったのですが、これらフォントはWindowsでのみ使用を認めているので、そのままフォントファイルをコピーしてRaspberryPiなどで使用するのはちょっと問題ありかなと思います。なので、今回はフリーのフォントであるIBM/plexフォントを使用します。

過去記事参考

インストールするフォントのリポジトリは以下になります。

github.com

今回はIBMPlexSansJP-Bold.ttfというフォントを使用していくことにします。 リポジトリからフォントを取得して画像生成を行うパスに予めコピーしておきます。

https://github.com/IBM/plex/blob/master/IBM-Plex-Sans-JP/fonts/complete/ttf/hinted/IBMPlexSansJP-Bold.ttf

取得は以下のようにします。

$ wget https://github.com/IBM/plex/raw/master/IBM-Plex-Sans-JP/fonts/complete/ttf/hinted/IBMPlexSansJP-Bold.ttf

f:id:ueponx:20220210002144p:plain

Node-RED拡張機能をインストールする(TwitterkuromojiDashBoradimage-outputbase64cron

拡張ノードのインストールは、フローエディタの左上にある、【三】(ハンバーガーメニュー)をクリックして、プルダウンメニューから【パレットの管理】をクリックして選択します。

f:id:ueponx:20220211144830p:plain

ユーザー設定のダイアログが開いたら【ノードを追加】タブをクリックし、

f:id:ueponx:20220211145236p:plain

入力ボックスに追加する拡張ノードの名前を入れて検索し、リスト表示された結果の【ノードを追加】ボタンをクリックしてインストール作業をしていきます。

f:id:ueponx:20220211150025p:plain

確認ダイアログが表示されたら、【追加】ボタンをクリックしてください。

f:id:ueponx:20220211145904p:plain

今回はデフォルトのノード以外に拡張ノードとして以下のものを使用していきます。

  • Twitter(node-red-node-twitter) … Twitterのツイートを取得する機能
  • kuromoji(node-red-kuromoji) … 日本語の分かち書き(品詞分解)を行う機能
  • DashBoard(node-red-dashboard) … 情報表示を行うWebダッシュボードの機能
  • image-output(node-red-contrib-image-output) … Node-REDのフローエディタ内に画像を表示するデバッグ向け機能
  • base64(node-red-node-base64) … バイナリデータをBASE64形式に変換する機能(image-outputのために必要)
  • cron(node-red-contrib-cron) … 定期実行の機能(cronの設定のように定期実行の設定ができる)

これらの拡張ノードのインストールに関しては、過去のエントリにも記載しているのでそちらを参照してください。

Twitter参考

uepon.hatenadiary.com

DashBoard参考

uepon.hatenadiary.com

uepon.hatenadiary.com

すべての拡張ノードをインストールしたら次に進めます。

フローを作成する

拡張ノードのインストールが終われば、あとはフローの作成になります。 今回は処理を大きく3つに分けています。

f:id:ueponx:20220211151602p:plain

  1. Twitterからツイートを取得し、正規表現で不要な情報を廃棄、分かち書きと品詞分解を行い必要なものだけをlog.txtに格納する
  2. 定期的にlog.txtを使用してwordcloud画像を生成し、Webダッシュボードに表示する
  3. 1時間毎に画像のバックアップとlog.txtの作り直し

1つ目をlog.txt生成フロー、2つ目をwordcloud画像表示フロー、3つ目をバックアップフローと呼ぶことにします。

フローは以下のように構成しています。

1)log.txt生成フロー

f:id:ueponx:20220211152255p:plain

基本的な動作は以下のようになります。

  1. Twitterからハッシュタグ検索をし取得されたツイートを取得。(TwitterAPIの認証に必要な情報は自身のアプリを作成し設定を行います)
  2. リツイートの情報でないものを取得。
  3. ツイートの本文のみを取得
  4. ツイート内のName、ハッシュタグ、URLなどを正規表現で削除
  5. Kuromoji分かち書きと品詞分解→リスト化されて出力
  6. 品詞(動詞、形容詞、形容動詞、固有名詞、名詞)のみ抽出
  7. 活用形のある品詞に関しては語句基本形を抽出
  8. 単語の取得
  9. 不要語句を削除(あまり意味のない単語はないほうがよいので)
  10. ログファイル(log.txt)に書き込み

4の処理は正規表現の部分が冗長なのでサブフロー化しました。

f:id:ueponx:20220211153315p:plain

正規表現での語句の入れ替えに関してはNode-REDchangeノードを使うと視認性が悪くなるのでfunctionノードで記述するか迷ったのですがサブフローにしています。

wordcloud画像表示フロー

f:id:ueponx:20220211152457p:plain

こちらのフローは以下の処理を行っています。

  1. 毎分毎トリガを生成
  2. 画像を生成(wordcloud_cliを実行)
  3. 画像をバイナリデータとして読み込み
  4. バイナリデータをbase64
  5. デバック用にフローエディタに表示
  6. Webのダッシュボードに表示

Dashboardに表示するときには画像のバイナリデータをbase64化する必要があるようです。画像用のタグはないのでDashboardtemplateノードにタグを直接記載しています。

バックアップフロー

f:id:ueponx:20220211152526p:plain

こちらのフローは以下の処理を行っています。

  1. 1時間毎にトリガを生成(cronで行っています)
  2. 時刻情報からバックアップ画像ファイル名を生成
  3. 画像ファイルのアーカイブ保存
  4. ログファイル(log.txt)の削除

基本的特に難しい点はありません。バックアップする画像のファイル名の生成でfunctionノードを使用している点がちょっと残念な印象です。

実行する

Node-REDのフローが実行状態であれば、reTerminal上のブラウザ(Chromium)でhttp://raspberrypi.local:1880/ui/を開けば、Webのダッシュボードで表示を観ることができるようになります。 そのままでは起動が面倒なので以下のようなシェルスクリプトを作成してみました。キオスクモードにしてもいいのかもしれませんが、今回は最大化とエラーの表示を制限するにとどめました。

start.sh

/usr/bin/chromium-browser --noerrdialogs --start-maximized --app=http://raspberrypi.local:1880/ui/

これで開発をしないというのであれば、chromium-autorun.serviceを使用するのも手かもしれません。

では実行の状態を確認してみます。

実行時のフローの様子

f:id:ueponx:20220213003837p:plain

ダッシュボードの様子

f:id:ueponx:20220213003856p:plain

reTerminalの実行の様子

f:id:ueponx:20220213003827j:plain

完成したフローは以下のリポジトリに格納しますので、無保証ですがお使いください。Twitterの認証に関してはダウンロードされたフローは空白になるので、その部分だけは入力を行ってください

GitHub

github.com

おわりに

今回、reTerminalを使用してみてわかったのですが、Node-REDとの相性がいいように感じました。

  • 開発してすぐに実行し設置デバイスとしても使える点(開発と実行デバイスの両立が即できる)
  • バイスに比較的大きなタッチパネル付き液晶があり情報の表示がNode-REDのWebダッシュボードで表示しやすい

想像以上にいいデバイスですね。最近の半導体不足によるRaspberryPiの入手の悪さに比較して、reTerminalは入手しやすいのもいいですね。 値段は少し張りますが、上記の利点を考慮すればその値段差もありかなと思ってしまいました。あとミニ三脚との組み合わせで手軽に持ち運べる点もいいと思います。

RaspberryPiの入手性。つらい。

f:id:ueponx:20220209235752p:plain

思った以上にNode-REDreTerminalの相性がいいので、今後はこちらに開発環境をシフトしたいなと考えています。

/* -----codeの行番号----- */