ラズベリーパイで情報発信ツールを作ろう!
前回は、Twitter APIを通してつぶやきを投稿するところまで進めることができました。続いて必要になるのは、つぶやきの本文!できるだけリアルタイムな情報を……ということで、RSSから取得した更新情報を投稿してみたいと思います。
RSSとは?
RSSといえば、おなじみのこのアイコン!
更新情報を教えてくれるためのURL?というようなぼんやりした知識しかなかったので、先に「RSS」について簡単におさらいです!
RSS – Wikipedia
RSSは、ニュースやブログなど各種のウェブサイトの更新情報を簡単にまとめ、配信するための幾つかの文書フォーマットの総称である。
RSS – e-words
RSSとは、Webサイトの見出しや要約などのメタデータを構造化して記述するXMLベースのフォーマット。主にサイトの更新情報を公開するのに使われている。
RSSはバージョンアップの過程で複数の系統に分裂し、互換性の無い状態となった。「RSS」のフルスペルもそれぞれ別のものを名乗っている。用途も微妙に異なるため、現在も複数のバージョンが並存している。
現在主に使われているのは、RSS1.0とRSS2.0の2つのバージョンです。フォーマットが異なるので、プログラムを書く際は注意しましょう。
それぞれの仕様については、Wikipediaからリンクされている英語のページに記載されています。
ちなみにDevicePlusのRSSは、サイドバーの下の方の……
ここにあります!(2015年7月現在のデザインです)
RSSはXMLで構成されているので、ブラウザで中身を見る事ができます。ブラウザによって見え方は異なるため、その場合はページのソースを開きましょう。ChromeではXMLがそのまま表示されます。
RSSのバージョンは、一番最初のタグに記載されているので確認しておきましょう。3行目の末尾に「version=”2.0″」とあるので、このRSSは「RSS2.0」ですね。
「channel」タグの直下にある「title」「link」「description」の3項目のみが必須項目となっています。各記事の情報はさらに下層の「item」タグ内に展開されています。必須項目と同じタグがここでも使われているので、間違えないように注意しましょう。
PHPでRSS情報を取得
RSSはXML形式のファイルなので、PHPの関数1つで取得可能です。下記は、「title」「link」「description」「pubDate」の4項目を出力するサンプルプログラムです。
/var/www/news/rss.php
<?php $rss_url = 'https://deviceplus.jp/feed/'; $xml = @simplexml_load_file($rss_url,'SimpleXMLElement',LIBXML_NOCDATA); if(isset($xml->channel)){ $channel = $xml->channel; //最終更新時刻を取得 $rssDate = $channel->lastBuildDate; date_default_timezone_set('Asia/Tokyo'); $lastBuildDate = strtotime($rssDate); foreach ($channel->item as $value) { $str = ''; $str .= '【title】'.$value->title ."<br/>"; $str .= '【link】'.$value->link ."<br/>"; $str .= '【description】'.$value->description ."<br/>"; $str .= '【pubDate】'.$value->pubDate ."<br/>"; $str .= "<hr />"; echo $str; } }
図4は、DevicePlusのRSSのデータを取得してみたところです。
記事のタイトルとURLに加えて、文字数を調整して「description」を追加すれば、より詳しい内容でツイートを投稿する事ができそうです。
「pubDate」には更新日時が設定されています。投稿のタイミングをはかる指標として利用できそうですね(この内容はまた次回!)。日時の値はRFC822という形式で記述されているため、日本語として読みやすいようにフォーマットを変換したほうが良さそうですね。
図5はURLをラズベリーパイ公式ブログのRSSに差し替えて実行したところ。「description」にはタグが入っている可能性があることが分かります。
RSS2.0の仕様によると、「title」と「description」のどちらか一方は必ず設定されていなければならないと記載されています。「link」は必須ではないようなので、URLは、
・「link」に記載されている
・「description」のHTMLに記載されている
上記のどちらか、ということになりそうですね。
このあたりはプログラム側で調整できる部分になるので、今回は割愛して、「link」にURLが設定されていることを前提に進めていきます。
Twitterの文字数制限について
Twitterといえば、1投稿(ツイート)につき140文字までという文字数制限があります。全角・半角の区別はなく、どちらも1文字としてカウントされます。
文章を140文字以内に調整するだけなら、プログラムで簡単にできますが、そこにはリンクのURLも含まれるの?と思って調べてみました。
Twitterのリンクサービス(http://t.co)に関するFAQ
Twitter.com上のリンク共有は、自動的にhttp://t.co リンクに短縮されます。
リンク(URL)をツイートする方法
リンクが22文字未満の場合でも、どんな長さのリンクも22文字に変更される。
実際にTwitterの投稿画面で目視確認してみましょう。
図6は、ツイート投稿用の入力ボックスに、URLを入力してみたところです。見た目はURLがそのまま表示されていますが、右下にある残り文字数のカウントを見てみると、
140 – 118 = 22
22文字!表示に関係なく、自動で短縮してくれているようですね。
ちなみに、ヘルプページには記載されていませんが、「https」ではじまるURLの場合は「23文字」となるようです。
図8は、前回作成した自動ツイートプログラムから投稿してみたところです。ツイート本文はURLがそのまま表示されていますが、カーソルを合わせてみると短縮URLが表示されています。
ブラウザから投稿する際、URLの前に半角文字をつなげて入力すると、URLとして認識されなくなり、文字数のカウントに含まれてしまいました。PHPを使った投稿ではきちんと認識されていたのですが、念のため半角スペースか改行で区切りを入れたほうが安全かもしれません。
ということで、短縮URLの23文字+余白の1文字で、必要な文字数は24文字!本文は最大116文字まで投稿できますね!
ラズベリーパイから投稿!
Twitterの投稿制限の内容を考慮して、前回作成したツイート投稿プログラムと連携させて見ましょう!
投稿されたかどうかが分かるように、LEDが点滅して教えてくれる機能も追加しました。
GPIOポートは、10番ピン(GPIO15)を使用しています。LEDについての解説は第9回目記事を参考にしてください。
/var/www/news/tweet_rss.php
<?php require_once("twitteroauth/autoload.php"); use Abraham\TwitterOAuth\TwitterOAuth; //認証 $consumerKey = '★★★★★'; $consumerSecret = '★★★★★'; $accessToken = '★★★★★'; $accessTokenSecret = '★★★★★'; $oAuth = new TwitterOAuth($consumerKey, $consumerSecret, $accessToken, $accessTokenSecret); //メッセージ作成 $pre_message = 'ラズベリーパイから発信!DevicePlus更新情報'; $rss_url = 'https://deviceplus.jp/feed/'; $rss_message = createRssMessage($rss_url, $pre_message); //ツイート投稿 tweetMessage($oAuth, $rss_message[0]); return; /* RSSを読み込んでツイート用メッセージを作成 */ function createRssMessage($rss_url, $pre_message=''){ $message = array(); $xml = @simplexml_load_file($rss_url,'SimpleXMLElement',LIBXML_NOCDATA); if(isset($xml->channel)){ $channel = $xml->channel; foreach ($channel->item as $value) { //ツイート本文作成 $str = $pre_message."\n"; if(isset($value->title )){ $str .= $value->title."\n"; } if(isset($value->description)){ $str .= strip_tags($value->description); } //文字数調整 if(mb_strlen($str)>116){ $str = mb_substr($str, 0, 115, mb_detect_encoding($str)).'…'; }else{ $str = mb_substr($str, 0, 116, mb_detect_encoding($str)); } $str = $str."\n"; //URL if(isset($value->link )){ $str .= $value->link; } $message[] = $str; } } return $message; } /* Twitterに投稿 */ function tweetMessage($oAuth, $message){ echo $message; //ツイート投稿 $response = $oAuth->post('statuses/update', array('status' => $message)); //結果 if(isset($response->errors)){ //エラー発生 foreach($response->errors as $err){ echo '【エラー】'.$err->message.PHP_EOL; } }else{ echo '【投稿完了】'.$response->text.PHP_EOL; //LED点滅 led(15,3); } } /* LED点滅 */ function led($pin, $count){ exec('echo '.$pin.' > /sys/class/gpio/export'); exec('echo out > /sys/class/gpio/gpio'.$pin.'/direction'); exec('echo 0 > /sys/class/gpio/gpio'.$pin.'/value'); for($i=0;$i<$count;$i++){ exec('echo 1 > /sys/class/gpio/gpio'.$pin.'/value'); sleep(1); exec('echo 0 > /sys/class/gpio/gpio'.$pin.'/value'); sleep(1); } exec('echo '.$pin.' > /sys/class/gpio/unexport'); }
実行コマンド
php /var/www/news/tweet_rss.php
前回に引き続き、「★★★★★」の部分はTwitter APIの各キー(Consumer key、Consumer secret、Access Token、Access Token Secret)に置き換えてくださいね。
各項目は、改行区切りで出力しています。ちなみに改行も「1文字」として認識されています。
140文字から、URLの23文字と区切り文字(改行)の1文字分を引いた「116文字」を投稿可能文字列の最大値として、それを超える場合は「…」を付加しています。
上記のサンプルでは、読み込んだRSSのうち1件目のみを投稿しています。全件投稿しても問題はありませんが、RSSに登録されている件数によっては、大量のツイートが行われる場合があります。事前に「item」タグの件数を確認しておきましょう。(DevicePlusは10件程度なので、全件投稿してもエラーなどは発生しませんでした)
くわしい投稿制限については、また次回!
投稿が成功すると、LEDが3回点滅してお知らせしてくれます。今回は会社のデスクに置いて使うことを想定して、音は出さずに、見た目だけで気が付きやすいようにチカチカさせてみました。
投稿されたツイートはこのようになりました。
140文字いっぱいまで情報を盛り込んでみたのですが、実際に見てみると、なんだかごちゃっとした印象に……このRSSの場合はあまり詰め込みすぎずにシンプルにまとめるほうが良さそうですね。
手作りらしく、ひとつひとつ丁寧に!投稿内容は、扱うRSSに合わせて調整してあげてくださいね!
RSS自体が取得できない場合は、RSSのXMLファイルが壊れていないか確認してみましょう。また、別の環境だとうまくいくのに、ラズベリーパイだとできない……そんなときは、「apache2」パッケージを最新のものにアップグレードすると解決する可能性がありますので、試してみてくださいね。(実際に謎のエラーに悩まされた際、これで解決できました!)
まとめ
RSSは意外と手強かったです……RSS1.0とRSS2.0で仕様が全く異なっていたり、必須項目が少なかったりと、調べるだけでもかなり苦戦してしまいました。
RSSの取得とTwitter投稿だけでは電子工作感が足りなかったので、電子工作ではおなじみのLEDを追加してみました。机の片隅でチカチカ光ってくれると意外と目に付きます!Twitter投稿とは別に、RSSの更新お知らせ用として活躍してくれそうです!
一連の流れができたので、残りは自動化の設定のみ!
このままだと一気に全件投稿されてしまうので、どこまで投稿したかを管理できるような仕組みが必要ですね。自動化するにあたって、エラーログも欲しいところです。
そんなわけで次回は、最後の仕上げの環境整備編です!