Development 更新

Twitter BOT の作成 第3回 — WordPress RSS の投稿情報をツイートする

今回は、WordPress の RSS を読み込み、投稿情報をツイートします。

先日から運用している WordPress の RSS から記事を取得してツイートする BOT を作ります。Azure Web サイトの Web ジョブを使います。

  • Visual Basic コンソールアプリ(LinqToTwitter 利用)
  • Microsoft Azure スケジューラによるジョブの実行

というニッチな内容です。無償の Visual Studio Express 2013 for Desktop で作れます。Azure は……。

WordPress のプラグインや Web サービスなどで良いものが見つからなかったので、手短に作ってみました。

目次

  1. BOT 用 Twitter アプリの作成
  2. ツイート コンソールアプリの作成
  3. WordPress RSS から投稿のツイート(今回)
  4. Azure スケジューラによるジョブの実行

WordPress の RSS フィードの構造

WordPress の出力する RSS フィードの URL は当サイトの場合、https://pronama.jp/feed/ です。フィードは、次のような構造になっています(不要な部分は省略しています)。

feed.xml
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" ... >
<channel>
	...
	<item>
		<title>[Web Comic] 情報処理研究会漫画 すぱこー Ver. 14</title>
		<link>https://pronama.jp/2014/07/22/web-comic-spaco-14/</link>
		<comments>https://pronama.jp/2014/07/22/web-comic-spaco-14/#comments</comments>
		<pubDate>Tue, 22 Jul 2014 13:50:22 +0000</pubDate>
		<dc:creator><![CDATA[jz5]]></dc:creator>
		<category><![CDATA[Pronama-chan]]></category>
		<category><![CDATA[Web Comic]]></category>
		<guid isPermaLink="false">https://pronama.jp/?p=48991</guid>
		<description><![CDATA[...]]></description>
		<content:encoded><![CDATA[...]]></content:encoded>
		<wfw:commentRss>https://pronama.jp/2014/07/22/web-comic-spaco-14/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	</item>
	<item>...</item>
</channel>
</rss>

ポイントとして、

  • 投稿は、<item> 要素ひとつで表されていて、複数個ある
  • タイトルは、<title> 要素
  • パーマリンクは、<link> 要素 もしくは、<guid> 要素(?=xxx 形式)
  • 日付は <pubDate> 要素
  • カテゴリーとタグは、どちらも <category> 要素(複数個)になっている

……という感じです。

今回は、各 <item> 内の <title> と <guid> の値を使います。?=xxx 形式の URL の方が短いので、こちらを使います。

追記: ツイート中の URL は、一定の文字数としてカウントされます。何文字分として扱われるかは、GET help/configuration | Twitter Developers の short_url_length と short_url_length_https の値からわかります。

WordPress の RSS フィードを読み込む

コードから RSS フィードを読み込みます。Visual Basic の場合はこんな感じ。

gistfile1.vb
Dim items = New List(Of String)

Dim d = XDocument.Load("https://pronama.jp/feed/")
For Each i In d...<item>
    Dim msg = String.Format("old post: {0} {1}", i.<title>.Value, i.<guid>.Value)
    items.Add(msg)
Next

<item> の数だけ繰り返し、<title>, <guid> の値から「old post: タイトル URL」の形式の文字列を作り、List に追加しています。

List から 1個だけランダムに返す関数にします。

gistfile1.vb
Private Function GetMessage() As String
    Dim items = New List(Of String)

    Dim d = XDocument.Load("https://pronama.jp/feed/")
    For Each i In d...<item>
        Dim msg = String.Format("old post: {0} {1}", i.<title>.Value, i.<guid>.Value)
        items.Add(msg)
    Next

    Dim r = New Random
    Return items(r.Next(items.Count))
End Function

以上で、RSS フィードを読み取り、ツイートメッセージを作る関数ができました。

ツイート部分の修正

前回 の Main 部分を、今回の GetMessage 関数を利用した形に修正します。また Try-Catch を付け例外処理もしています(単にコンソールにメッセージを出力しているだけですが)。

Module.vb
Sub Main()
    Dim t = Task.Factory.StartNew(
        Async Function()
            Dim msg = GetMessage()
            Await Tweet(msg)
        End Function).Unwrap

    Try
        t.Wait()

    Catch aEx As AggregateException
        For Each e In aEx.InnerExceptions
            Console.WriteLine(e.Message)
        Next
    Catch ex As Exception
        Console.WriteLine(ex.Message)
    End Try
End Sub

以上で、1度起動すると、WordPress の投稿をランダムに選んで、1回ツイートして終了するプログラムの完成です。

プログラムで留意していないこと

今回作成したプログラムは、定期的に実行し、WordPress の投稿をツイートするために使います。その際、考慮していないことがいろいろあります。改良の参考にしてください。

同一のツイート

2回以上実行して、ランダムに選択した投稿が同じ場合、重複ツイートとなり、ツイートできない可能性があります。

今回は、重複したらあきらめる運用とします。プログラムの修正案としては、日付やランダムな数値をメッセージに付けたし重複しないメッセージの作成などがあります。

140 文字より長いツイート

タイトルと URL の長さが140文字より長い場合、ツイートできません。

今回は、長いタイトルを投稿しないという前提とします。プログラムの修正案は、タイトルが長い場合、メッセージが140文字に収まるよう、短く省略する方法があります。

その他のエラー

WordPress のフィード読み込み時や、ツイート時のエラーは何も考慮していません。ツイート時に何かしらエラーが発生した場合は、リトライ等せず、その回はあきらめる運用とします。

ツイートしたくない投稿の除外

今回、RSS フィードに含まれるすべての投稿が、ツイート対象です。より細かな動作ができる BOT のためには、ツイートから除外したい投稿(たとえばイベント告知で期限切れなど)は、カテゴリーやタグで判別したり、別途 除外用のリストを作成して対応が必要です。

古い投稿のツイート

RSS フィードには最新の投稿しか含まれていないため、古い投稿をツイートできません。古い投稿に対応するには、フィード内容を保存しておくなどの対応が必要です。

今回はここまでです。第4回 へ。