目次


Twitter のリストを RSS に変換する

Twitter のリスト・ウィジェットからのフィードを構文解析し、Bluemix にデプロイして公開する

Comments

Twitter には、Twitter フィードを Web サイトに組み込むためのカスタム・ウィジェットが用意されています。フィードの取得元としては、自分のツイートや「いいね」、Twitter リスト、Twitter 検索の結果など、さまざまなソースを指定することができます。2006年に Twitter サービスが開始された当時、ウィジェットでは XML、Atom、JSON、RSS を含む複数のフォーマットでフィードを生成することができましたが、2012年 9月にリリースされた Twitter API 1.1 で、JSON を除くすべてのフォーマットが非推奨となりました。

皆さんの中には、私のように、RSS が使えなくなったことをとりわけ残念に思っている方もいることでしょう。RSS フォーマットのフィードはメール・クライアントでも、ブラウザーのフィード・リーダーでも、RSS 専用のリーダー・ソフトウェアでも読み取ることができて便利でした。また、RSS であれば簡単に、このリンク先の IFTTT.com 上に用意されているレシピを統合して自動化することもできます。

このチュートリアルでは RSS の支持者を支援するために、Twitter ウィジェットから JSON フィードを取得して構文解析し、RSS フィードとして返すための単純な Node.js スクリプトを作成します。このスクリプトでは、REST 呼び出しを使用してウィジェットからのフィードを取得し、そのフィードを node-elementtree モジュールによって構文解析した後、その結果を RSS フィードとして Express ルートから返します。

最後のステップとして、ユーザーがブラウザーでフィードを読んだり、他のプログラムからフィードを購読したりできるよう、RSS フィードを IBM Bluemix にデプロイします。このチュートリアルでは Twitter のリスト・ウィジェットを操作しますが、どの Twitter ソースから作成されたウィジェットに対しても、これと同じ方法を適用することができます。

必要となるもの

アプリを実行するコードを入手する

ステップ 1. Twitter リストを作成する

デスクトップ・ブラウザーで、Twitter アカウントにログインします。ページの右上に表示されている自分のプロフィール写真をクリックし、メニューから「Lists (リスト)」を選択します。既存のリストと一緒に (リストが既にある場合)、「Create new list (新しいリストを作成)」ボタンが表示されます。以下に示すリンクのリンク先ページの指示に従って、お好みのリストを新規に作成します。

このチュートリアル用に、私はお気に入りの作家からなる「Writers」リストを Twitter 上に作成しました。

Twitter リストのスクリーンショット
Twitter リストのスクリーンショット

ステップ 2. Twitter ウィジェットを作成する

  1. 自分の Twitter プロフィール写真をクリックし、「Settings (設定)」を選択します。
  2. 設定ページの左側のメニューから「Widgets (ウィジェット)」を選択し、「Create new (新規作成)」をクリックします。
  3. 「Choose a timeline source (タイムラインソースを選択)」セクションで「List (リスト)」タブを選択し、ステップ 1 で作成したリストを選択してから、「Create widget (ウィジェットを作成)」をクリックします。まもなくすると、このウィジェットに組み込まれる HTML コードがテキスト・ボックスに表示されます。
  4. 組み込みコードを安全な場所にコピーして、anchor タグ内の data-widget-id 値をメモしておきます。

ステップ 3. ウィジェットのフィードを取得する

  1. システム上に空のディレクトリーを作成し、カレント・ディレクトリーをそのディレクトリーに変更します。
  2. コマンド・ラインから以下の npm コマンドを実行して、新しい Node.js プロジェクトを作成します。

    npm init

    ほとんどの項目はデフォルト値のままで構いません (npm の最新リリースでは、プロジェクト名に大文字を使用できないことに注意してください)。
  3. コマンド・ラインから以下のコマンドを実行して、request モジュール (Node REST クライアントのデファクト・スタンダード) をプロジェクトに追加します。

    npm --save install request

    オプションの --save フラグによって、このモジュールが package.json 内のプロジェクト依存関係に追加されるため、手作業でモジュールをファイルに追加する手間が省かれます。

  4. スクリプト・コード用の空のファイルを作成し、package.json ファイル内の main 属性値と同じ名前 (通常は、index.js) を指定します。以下のコードを index.js に追加します。<widget ID> の部分は、ステップ 2 で作成したウィジェット ID の値で置き換えてください。
    var request = require('request');
    
    request.get("http://cdn.syndication.twimg.com/widgets/timelines/<widget ID>",
    	function(err, resp, body) {
    
    });

    すべての Twitter リスト・ウィジェットには、上記のスニペットに示されている REST エンドポイント (http://cdn.syndication.twimg.com/widgets/timelines/<ウィジェット ID>) からアクセスすることができます。REST 呼び出しが正常に完了すると、匿名関数の body 変数に Twitter フィードが格納されます。

以降の 3 つのステップで index.js 構文解析スクリプトのコードを作成した後、ステップ 6 ですべての構成要素を 1 つに組み立てます。

ステップ 4. フィードに修正を適用する

REST 呼び出しからのレスポンスは有効な JSON ですが、形式はプレーン・テキストなので、Node の組み込み JSON パーサーを使用してレスポンスを JSON オブジェクトに変換します。構文解析スクリプトでは、node-elementtree XML パーサーで構文解析できるよう、以下の変更をオブジェクトの body 属性に適用する必要もあります。

  • 改行文字やキャリッジ・リターン文字のすべてを、正規表現の \r および \n を使用して削除します。
  • 連続するスペースのすべてのインスタンスを、正規表現の \s を使用して 1 つのスペースで置き換えます。
  • <img> タグ (HTML では正しく閉じられますが、XML ではそうではありません) を削除します。
  • <time> タグから空の <time> 属性 (HTML では許容されますが、XML では許容されません) を削除します。
  • &lrm;&amp; などの Unicode 文字を、正規表現 &.*?; を使用して検索して削除します。

以上の修正を行うには、以下のコードを使用してください。

var json = JSON.parse(body);
var list = json.body.replace(/(\r\n|\n|\r)/gm, " ")
 		     .replace(/\s+/g, " ")
		     .replace(/<img.*?>/gi, "")
		     .replace(/pubdate/gi, "")
		     .replace(/&.*?;/gi, "");

ステップ 5. 修正後のフィードを構文解析して RSS を返す

ここまでの手順でフィードは有効な XML となったので、node-elementtree Node.js モジュールを使用して構文解析をすることができます。

  1. コマンド・ラインから以下のコマンドを使用して、node-elementtree をインストールし、package.json ファイルに追加します。

    npm --save install elementtree

  2. 以下のコードをスクリプトに追加して、XML がドキュメント・ツリーに構文解析されるようにします。
    var etree = et.parse(list);
  3. RSS フィードには少なくとも以下のノードが含まれている必要があります。
    • title: RSS フィードのタイトル
    • link: フィードに関連する Web サイトへの HTML リンク
    • description: フィードの説明
    以上の情報は、以下のフォーマットで XML ドキュメントに保管されます。
    <?xml version="1.0" encoding="UTF-8"?>
    <rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
       <channel>
          <title>RSS Feed Title</title>
          <link>RSS Feed Link</link>
          <description>RSS FEED</description>
       </channel>
    </rss>
    XPath 式を使用することで、ドキュメント・ツリーから以下の値を取得することができます。
    • リストのタイトルは、div/h1 に位置するノードから取得することができます。
    • div/h2/a に位置するノードの href 属性から Twitter ページの URL を取得します。その URL に /lists/ パスとリスト名を組み合わせてリストの URL を構成します。
    • 説明は、div/p に位置するノードから取得することができます。
    以上の値を使用して、レスポンスとして返す RSS フィードの作成を開始します。
    var et = require('elementtree');
    
    var title = etree.findtext('div/h1');
    var link = etree.find('div/h2/a').get("href");
    var description = etree.findtext('div/p');
    var rss = '<?xml version="1.0"?><rss version="2.0" ;
    rss += '<channel><title>' + title + '</title>';
    rss += '<link>' + link + '/lists/' + title + '</link>';
    rss += '<description>' + description + ' </description>';
    rss += "</channel></rss>";
  4. フィードで返されるツイートは、HTML で編成された <ol> リスト内に <li> リスト項目エントリーとして格納されます。リスト項目のすべては、etree.findall() 呼び出しによって div/div/ol/li パスから配列として取得されます。

    各ツイートを使用して、rss フィールド内に新しいエントリーを作成します。RSS の仕様によると、フィード内の RSS エントリーには title フィールドまたは description フィールドが含まれていなければなりません。これ以外には必須フィールドはありません。

    以下のコードを使用して、RSS ストリングに新しいエントリーのそれぞれを追加します。

    var tweets = etree.findall('div/div/ol/li');
    for (var counter = 0; counter < tweets.length; counter++) {
        
       var tweet = tweets[counter];
       var tweetTitle = tweet.findtext('div/p').trim();
       var author = tweet.findtext('div[@class="timeline-Tweet u-cf js-tweetIdInfo"]/' +
                        'div[@class="timeline-Tweet-author"]/' +
                        'div/a/span[@class="TweetAuthor-screenName Identity-screenName"]');
                                    
       var tweetPermalink = tweet.find('div/div[@class="timeline-Tweet-metadata"]/a')
                                 .get('href');
       var pubDate = Date.parse(tweet.find('div/div[@class="timeline-Tweet-metadata"]/a/time')
                                     .get('datetime'));
        
       rss += "<item>";
       rss += "<title>" + tweetTitle + "</title>";
       rss += "<pubDate>" + new Date(pubDate).toUTCString() + "</pubDate>";
       rss += "<guid>" + tweetPermalink + "</guid>";
       rss += "<link>" + tweetPermalink + "</link>";
       rss += "<description><![CDATA[  " + author + ": " + tweetTitle + "]]></description>";
       rss += "</item>";
        
    }

    上記のコードでは、各項目を作成するために、以下の要素を使用しています。
    • タイトルとして、div/p ノードから取得されるツイートのテキストを使用します。
    • 作成者として、後続ノードから以下の XPath 式によって選択される Twitter ハンドルを使用します (以下のコードは、ページの幅に収まるよう 2 行に分割されています)。
      div[@class="timeline-Tweet u-cf js-tweetIdInfo"]/div[@class="timeline-Tweet-author"]/
      div/a/span[@class="TweetAuthor-screenName Identity-screenName"]
    • リンクおよび guid として、div/div[@class="timeline-Tweet-metadata"]/a に位置するノードの href 属性に含まれるツイート URL を使用します。
    • 説明として、作成者とツイート・テキストを組み合わせて使用します。
    さらに、RSS 項目の pubdate フィールドは RFC-822 フォーマットでなければなりません。JavaScript の Date オブジェクトは、UTCString() メソッドを使用することで、このフォーマットで日付を返すことができます。div/div[@class="timeline-Tweet-metadata"]/a/time に位置するノードの datetime 属性を Date.parse() メソッドに渡すと、1970年 1月 1日からの経過時間がミリ秒数で返されます。この値を使用して新しい Date オブジェクトを作成し、toUTCString() メソッドを呼び出して正しい値を取得します。

RSS ストリングは、このリンク先の W3C「Feed Validation Service」に照らし合わせて検証することができます。

ステップ 6. Express ルートから RSS を返す

次は、Web サービス呼び出しから RSS ストリングを返すように Express サーバーを構成する方法を説明します。

  1. コマンド・ラインから以下のコマンドを使用して、Express をインストールします。

    npm --save install express

  2. index.js の先頭に、Express サーバーを作成するための以下のコードを追加します。
    var express = require('express');
    app.set('port', process.env.PORT || 3000);
    http.createServer(app).listen(app.get('port'), function(){
        
        console.log('Express server listening on port ' + app.get('port'));
    
    });
    
    app.get('/', function(request, response) {
    
    });
  3. 次に続くのは (ステップ 3 で作成した) ウィジェットのフィードに対する、リクエストによる呼び出しです。リクエストによる呼び出しの後に、ステップ 4 で作成したフィード修正コードと、ステップ 5 で作成した構文解析コードを追加します。最後に、res.send(rss); を呼び出して、完成した RSS フィードをユーザーに返します。
  4. コマンド・ラインから、以下のコマンドを使用してサーバーを起動します。

    node index.js

  5. ブラウザーで http://localhost:3000/ にアクセスし、結果を表示します。以下に、Firefox でレンダリングされた、私の Writers リストからのフィードのスナップショットを示します。Writers リストの RSS フィードのスクリーンショット
    Writers リストの RSS フィードのスクリーンショット

このサーバーがリクエストをリッスンする場所は、リクエストのデフォルト・パス (/) です。app.get 呼び出しに含まれるこのパスは、設定を変更することができます。

ステップ 7. Bluemix にデプロイする

  1. Bluemix DevOps Services にログインして、新しいプロジェクトを作成します。Bluemix 上に新しい Git リポジトリーが作成されるように項目を選択します。残りの選択項目については、デフォルト値を使用します。
  2. OS のコマンド・ラインから以下のコマンドを使用して、作成したリポジトリーをローカルに複製します。

    git clone --no-checkout https://hub.jazz.net/git/<ユーザー名>/<プロジェクト名>
    cd <プロジェクト名>
    echo "# readme" >> README.md
    git add README.md
    git commit -m "first commit"
    git push -u origin master

  3. ローカル Node.js プロジェクト・ディレクトリー内の package.json ファイルと index.js スクリプト・ファイルを新しいプロジェクト・ディレクトリーにコピーします。
  4. 新しいディレクトリーから、この 2 つのファイルをコミットしてプッシュします。
  5. Bluemix DevOps Services 上のプロジェクトで、「BUILD & DEPLOY (ビルドおよびデプロイ)」をクリックします。
  6. 「ADD STAGE (ステージの追加)」をクリックし、「JOBS (ジョブ)」タブを選択します。
  7. 「ADD JOB (ジョブの追加)」をクリックし、「Deploy (デプロイ)」を選択します。「Organization (組織)」と「Space (スペース)」に正しい値が設定されていることを確認してから、「SAVE (保存)」をクリックします。
  8. 変更が完了したら、「RUN STAGE (ステージの実行)」ボタンをクリックして Bluemix にデプロイします。
  9. デプロイが完了した後、Bluemix の URL にアクセスすると、新しい RSS フィードが表示されます。

まとめ

このチュートリアルでは、Twitter のリスト・ウィジェットからの出力を構文解析して RSS フィードを作成する方法、そしてそのフィードを Bluemix にデプロイしてオンラインで利用できるようにする方法を概説しました。さらに開発を進める上での提案を以下に記載します。

  • このチュートリアルで作成したスクリプトが読み取るのは、ここで作成したウィジェットだけです。リクエストによる呼び出しと Express ルートに変更を加えてウィジェット ID をパラメーターとして渡せるようにすることで、任意のウィジェットのフィードを読み取ることができるようになります。
  • リツイートのフォーマットは、通常のツイートのフォーマットとは少し異なるため、作成者および公開日の正しい値、そしてツイートのテキストを取得するには、別の XPath セレクターが必要になります。完全なフィードを XML ビューアーで表示して、これらの属性の正しい値を取得してください。
  • あらゆる Node.js モジュールには、代替モジュールを使用できるようになっています。他のモジュールを使用して RSS フィードを作成する場合に必要になる変更を調べてください。
  • RSS フォーマットには、さまざまなオプション要素を含めることができます。RSS の仕様を読んで、ノードを使用してウィジェットのフィードからこれらの要素を含める方法を調べてください。
  • これは必須ではありませんが、RSS フィードに atom:link 要素を含め、href 属性をそのフィードの URL に設定することをお勧めします。この要素をコードに追加する際は、URL を Bluemix 上にデプロイしたコードの値に設定します。
  • RSS 内のツイートにリンクやハッシュタグが含まれていると、ツイートのテキストが切り取られてしまいます。リンクおよびハッシュタグからのテキストを RSS 項目ノードの description フィールドに含める方法を調べてください。

ダウンロード可能なリソース


関連トピック


コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Web development, Cloud computing
ArticleID=1035453
ArticleTitle=Twitter のリストを RSS に変換する
publish-date=07282016