SSブログ
RSS [RSS1.0] [RSS2.0]
共謀罪を含む改悪組織犯罪処罰法は
【「共謀罪」法 衆参両院議員の投票行動(東京新聞 2017/6/16)】

Twitterで取得したユーザーのJSONデータをRSSフィードに変換する(GAEを使う)

追記(2017/12/28):
この記事に載せたアプリは2017/12/28に削除しました。

追記(2017/11/19):
この記事に載せたアプリは削除することにしました。
理由は次の通りです。
このアプリを動かすために Google App Engine(GAE)を利用していましたが、サービスが変更になったようで、私の能力では対応しきれなくなりました。プログラムの変更はありませんので、このまま使い続けられるのかもしれませんが、プログラムの変更が必要になった時に困るので、サーバーから、全てのファイルを削除しようと思っています。
申し訳ありませんが、利用していた方は、できるだけ速やかに、別のサービスに移ってください。
よろしくお願いします。m(_ _)m
なお、アプリの削除日時は未定です。突然削除することになると思いますが、ご了承ください。
今までご利用くださり、ありがとうございました。m(_ _)m

 【TwitterのAPI 1.1で取得したユーザーのJSONデータからRSSフィードを作成する】の続き。

 Google App Engine(GAE)でPHPが利用できるようになっていたと知って(参照)、それならばPHPサーバーを借りずにGAEだけでツイッターのRSSフィードを作成できるのではないかと試してみた。しかし、私の能力では一つのアプリで11個あるphpファイルを叩くことができなかった。また、phpファイルを叩くことで生成されるxmlファイルを見ることもできなかった。デプロイする前にGoogle App Engine Launcherを使ってローカル環境ではxmlファイルを作ることができたのだが、デプロイした後のGAEの中では方法が分からなかった。xmlファイルが見られない、生成されない原因は、後述するようにtwitteroauth.phpの問題だったのかもしれないが、方針を大転換することにした。
 【TwitterのAPI 1.1で取得したユーザーのJSONデータからRSSフィードを作成する】では8分間隔でxmlファイルを作成しておき、ThunderbirdなどのRSSリーダーで既に作られているxmlファイルにアクセスしていた。これを、RSSリーダーでアクセスした時にRSSフィードが生成されるように変更することにした。これであれば、複数のphpファイルを叩く必要はなく、一つのphpファイルで複数のRSSフィードを生成できる。アクセスするURLに取得したいツイートのアカウントと、取得したいツイートの件数を記載して、それをphpファイルが参照してRSSフィードを生成して表示する。これは、意外とあっさりとできた。例えば、次のURLにアクセスすると、私のツイートのRSSフィードが表示される。

 http://tweet-rss.appspot.com/?name=self7777&count=10

 上のURLのnameは取得したいツイートのアカウントで、「self7777」を変えれば生成されるRSSフィードが変わる。countは取得したいツイートの件数で、「10」を変えればRSSフィードに表示されるツイートの件数が変わる。「20」なら20件のツイートが表示される。nameにアカウントが記入されてなかった場合は強制的に「self7777」のRSSフードを表示することにし、countに数が記入されてなかった場合や0以下だった場合は強制的に「10」件のツイートを表示することにした。また、「name=」や「count=」がURLに記載されてなかった場合はそれらを入力するためのトップページが表示されるようにした。

 http://tweet-rss.appspot.com/
 (注意:非公開のアカウントのRSSフィードは作れない
 (注意:2018年になる前に削除します。

追記(2014/6/12):
 2014/6/12の10:28頃から使えなくなっています。まずはJSONの取得ミスが頻発してGAEの無料利用分を使い果たしたために、次のようなエラーを返しているようです。
Over Quota
This application is temporarily over its serving quota. Please try again later.
 使えるようになる時期は不明です。(2014/6/12の17:20頃には使えるようになったようです。)
 ご利用下さった方々、申し訳ありません。m(_ _)m

 このためのphpファイルの記載は次のとおり。

<?php
header("Cache-Control: max-age=0");

if(isset($_GET['count']) && isset($_GET['name'])) {
    $listcount = $_GET['count'];
    $name = $_GET['name'];
    if($listcount < 1){$listcount = "10";}
    if($name == ""){$name = "self7777";}

require_once("twitteroauth-master/twitteroauth/twitteroauth.php");
date_default_timezone_set('Asia/Tokyo');

$consumerKey = "xxxxxxxxxxxxxxxxxxxxxx";
$consumerSecret = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
$accessToken = "";
$accessTokenSecret = "";

$connection = new TwitterOAuth($consumerKey,$consumerSecret,$accessToken,$accessTokenSecret);

$request = $connection->OAuthRequest('https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=' . $name, "GET", array("count"=>$listcount));

$results = json_decode($request);
if (is_array($results)) {
    $status = "/status/";
} else {
    $results = array(0=>(object) array("created_at"=>date('D, d M Y H:i:s +0900'),"id_str"=>"","text"=>"エラー:RSSフィードは作られませんでした。ツイートの取得に時間がかかり過ぎたか、非公開アカウントだったようです。"));
    $status = "";
}

//var_dump($results);break;

//if (isset($results)) {
    echo '<?xml version="1.0" encoding="utf-8"?>' . "\n";
    echo '<?xml-stylesheet href="stylesheets/tweet-rss.xsl" type="text/xsl" ?>' . "\n";
    echo '<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">' . "\n";
    echo '<channel>'. "\n";
    echo '<atom:link href="http://tweet-rss.appspot.com/?count=' .$listcount."&name=". $name . '" rel="' . $name . '" type="application/rss+xml" />' . "\n";
    echo '<title>RSS (@' . $name . ")</title>\n";
    echo '<link>' . 'https://twitter.com/' . $name . '</link>' . "\n";
    echo '<description>ツイッター公式RSS配信中止で代わりに作成。URLのcomの後ろに「/?count=20&name=self7777」などを追加して利用する。countは取得件数。「20」の所を別の数字にすれば取得件数を変えられる。nameは取得したいツイートのアカウント。「self7777」の所を別のIDに変えれば取得できる。ただし、非公開アカウントのRSSフィードは作れない。</description>' . "\n";
    echo '<lastBuildDate>';
    foreach ($results as $key => $val) {
        echo date('D, d M Y H:i:s +0900', strtotime($results[$key]->created_at));
        break;
    }
    echo '</lastBuildDate>' . "\n";
    echo '<language>ja</language>' . "\n\n";
    foreach ($results as $key => $val) {
    echo '<item>' . "\n";
    echo '<link>' . 'https://twitter.com/' . $name . '/status/'$status . $results[$key]->id_str . '</link>' . "\n";
    echo '<guid isPermaLink="true">' . 'https://twitter.com/' . $name . '/status/'$status . $results[$key]->id_str . '</guid>' . "\n";
    echo '<pubDate>' . date('D, d M Y H:i:s +0900', strtotime($results[$key]->created_at)) . '</pubDate>' . "\n";
    echo '<title>' . "\n" . htmlspecialchars($results[$key]->text) . "\n" . '</title>' . "\n";
    echo '<description><![CDATA[' . "\n";
    echo $results[$key]->text;
    echo "\n" . ']]></description>' . "\n" . '</item>' . "\n";
    }
    echo '</channel>' . "\n" . '</rss>' . "\n";
//}

} else {

echo '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' . "\n";
echo '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">' . "\n";
echo '<head>' . "\n";
echo '<meta http-equiv="Content-type" content="text/html; charset=UTF-8" />' . "\n";
echo '<meta http-equiv="Content-style-type" content="text/css" />' . "\n";
echo '<link rel="index" href="http://twitter.com/self7777" />' . "\n";
echo '<link rev="made" href="http://twitter.com/self7777" />' . "\n";
echo '<title>ツイートのRSSを表示する</title>' . "\n";
echo '</head>' . "\n";
echo '<body>' . "\n";
echo '<div style="text-align:left; padding:10px;width:80%;">' . "\n";
echo '<form method="get" action="http://tweet-rss.appspot.com/" id="tweet-rss" name="tweet-rss">' . "\n";
echo '取得したいツイートのアカウント:@' . "\n";
echo '<input type="text" name="name" size="30" value="" style="width:100px;" /><br />' . "\n";
echo '取得したいツイートの件数   : ' . "\n";
echo '<input type="text" name="count" size="30" value="20" style="width:100px;" />' . "\n";
echo '<input type="submit" value="RSS表示" />' . "\n";
echo '</form>' . "\n";
echo '<div style="color:red;font-weight:bold;">注意:非公開アカウントではエラーになり、RSSフィードは作れません。</div>' . "\n";
echo '</div>' . "\n";
echo '</body>' . "\n";
echo '</html>' . "\n";

}

?>

 consumerKeyとconsumerSecretは入力したが、accessTokenとaccessTokenSecretは入力しなくても動作した。このアプリからはツイートせず、JSONを取得するだけなので不要なのかもしれない。しばらく使ってみて入力しなければ動かなくなったら入力する。(追記(2014/1/15):accessTokenとaccessTokenSecretは非公開のアカウントのRSSフィードを作るために必要。ただし、accessTokenとaccessTokenSecretを記入することで取得できる非公開アカウントはフォローしている場合に限る。

 ところで、このスクリプトはGoogle App Engine Launcherを使ったローカル環境では動作するのにGAEにデプロイすると動作しない状態が続いた。キャッシュが原因ではないかといろいろと調べたのだが、どうやらOAuth認証に失敗しているようだった。
 【【PHP】【GAE】PHPでtwitterBot & GAEにデプロイ - せかいや】によると、「GAEではcurlが使えない」ということで、twitteroauth.phpをGAE上で使いたい場合はコードを修正する必要があるらしい。どのように修正するか書いてくださっていたのだが、どこに記入するのか分からなくて別のサイト【PHPでTwitterのbotを作る方法 ツイートをする/ツイート一覧を取得する - [サンプルコード/PHP] ぺんたん info】を参考にしていた。ここに、「CURL関数が使用できない場合」のtwitteroauth.phpの修正方法が書いてあって、これを参考にしたことで、Google App Engine Launcherを使ったローカル環境で使えるようになっていた。それで安心したのが間違いで、やはり【【PHP】【GAE】PHPでtwitterBot & GAEにデプロイ - せかいや】で紹介されている方法でtwitteroauth.phpを修正する必要があった。「作成したBOTのコード」でソースコードを確認したら修正個所が分かった。次のように修正されていた。

 元のtwitteroauth.phpの193行目の次の部分。

  function http($url, $method, $postfields = NULL) {

 これを次のように変更する。

  function http($url, $method, $postfields = null) {
      if (function_exists('curl_init')) {
          return $this->httpCurl($url, $method, $postfields);
      }
      return $this->httpNoCurl($url, $method, $postfields);
  }
  
  function httpNoCurl($url, $method, $postfields = null) {
      $headers = array(
              'Content-Type: application/x-www-form-urlencoded',
              'Content-Length: '.strlen($postfields),
      );
      $options = array('http' => array(
              'method' => $method,
              'content' => $postfields,
              'header' => implode("\r\n", $headers),
      ));
      
      $contents = file_get_contents($url, false, stream_context_create($options));
      return $contents;
  }
  
  function httpCurl($url, $method, $postfields = null) {

 修正されたソースコードの7行目に次のように書いてある。

*
* NOTICE:
* Sekai(https://github.com/sekaiya) add httpNoCurl() methond.
*

 元の関数http()をhttpCurl()に変更して、curl_init()が使えない場合は新たに追加したhttpNoCurl()を使うように修正されている。私はtwitteroauth.phpをコピーして使わせて頂いたことにより、RSSフィードを生成するアプリがGAEにデプロイしても使えるようになった。感謝。m(_ _)m

 さて、私のアプリで生成されたRSSフィードにはヘッダに次のような行がある。

<?xml-stylesheet href="stylesheets/tweet-rss.xsl" type="text/xsl" ?>

 生成したRSSフィードの表示形式をxslファイルtweet-rss.xslで変えられないかと試したのだが、これは成功していない。GAEの使い方をちゃんと勉強してないからだろう。
 ちなみに、app.yaml は次のように書いておいた。

application: tweet-rss
version: 1
runtime: php55
api_version: 1
threadsafe: yes

handlers:
- url: /favicon\.ico
  static_files: favicon.ico
  upload: favicon\.ico

- url: /stylesheets
  static_dir: stylesheets

- url: .*
  script: tweet-rss.php

 アプリで表示されたRSSフィードをダウンロードして確認すると、tweet-rss.xslが適用されて表示形式が変わるのだが、GAE上ではGoogle App Engine Launcherを使ったローカル環境でもtweet-rss.xslが無視される。tweet-rss.xslの記述が間違っているのではなく、GAEの使い方を間違えているのだろうが、私の能力では分かりそうにないので諦めた。私個人の利用に関しては、表示形式を変える必要は全く無いので…。

 TwitterのRSSフィードを作ってくれるアプリはたくさんある。しかし、私が確認した中ではツイートの表示件数を変えられるアプリが無かったので、自分で作るしかなかった。私が見ているアカウントの中には1日見ないと100件を超えてしまうものもあり、10件とか20件しか表示してくれないようだと不十分だった。【TwitterのAPI 1.1で取得したユーザーのJSONデータからRSSフィードを作成する】では、作成したxmlファイルのURLは公開しなかったが、今回のアプリではURLを公開することにした。accessTokenとaccessTokenSecretを入力しなくても動作している件が気になる(追記(2014/1/15):accessTokenとaccessTokenSecretは非公開のアカウントのRSSフィードを作るために必要。ただし、accessTokenとaccessTokenSecretを記入することで取得できる非公開アカウントはフォローしている場合に限る。)が、どなたか、使ってみて頂きたい(注意:GAEのログに生成したRSSフィードのアカウントと件数と使ったブラウザの種類が表示されるようです)。何らかの事情でアプリが使えない状況があったら、その時に私の能力で可能な範囲で何らかの修正をしたいと思う。

追記(2015/10/3):
 上記の「phpファイルの記載」について、OAuthRequestの意味が分からなくて調べていたら、次のような情報があった。

「PHP TwitterOAuth 1.1」でググると、

$TwitterOAuth->OAuthRequest("http://api.twitter.com/1.1/statuses/update.json","POST",array("status"=>$tweet));

みたいなコードばっかり引っかかってぅぇぇとなるんですが。
誰かが最初に適当に書いたのをみんながコピペしたという過去が透けて見えるようだ。
まあ、動けばそれでいいというPHPの精神には則っているかもしれませんね。

PHP - TwitterOAuthの正しい使い方 - Qiita

 私もコピペなので「ぅぇぇ」となるコードを使ってる。

oAuthRequest()はJSONデコードもされていないし、このメソッドを直接呼ぶ意義は、今のところ全くありません。
PHP - TwitterOAuthの正しい使い方 - Qiita

 それで、正しい使い方を紹介してくれているのだが、【TwitterOAuth PHP Library for the Twitter REST API】を見ても同じように書いてある。
 このページをコピペしようとしている人は修正した方が良いだろう。
 私は面倒なのでこのまま使うが…。

 さらに、TwitterOAuthも新しくなっているらしく、このページに書いてある方法ではダメかもしれない。私は古いTwitterOAuthをダウンロードして使っているのだが、TwitterOAuthの使い方がよく分からないので新しくしないことにする。
 この追記を書いている時は「v0.6.0」らしい。リリース年月日はたぶん「2015-09-08 17:28 UTC」。

 新しい参考ページ→【TwitterOAuth - PHPからTwitterツイート(2015年2月版) - Qiita】

追記(2017/5/16):

 元の関数http()をhttpCurl()に変更して、curl_init()が使えない場合は新たに追加したhttpNoCurl()を使うように修正されている。私はtwitteroauth.phpをコピーして使わせて頂いたことにより、RSSフィードを生成するアプリがGAEにデプロイしても使えるようになった。感謝。m(_ _)m
 「curl_init()が使えない場合は」とあるが、使えないことが分かっているのなら、 if (function_exists('curl_init')) で確認する必要はなく、最初から httpNoCurl() を使ってしまえば良いのではないだろうか。どうやらGAEが仕様変更されたのかバグが発生しているのか、課金を有効にしてcurlを使えるようにしていないにもかかわらず、上記のコードでは httpNoCurl() ではなく httpCurl() の方で動作してエラーになり正常に機能しない問題が生じているらしい。それが原因の異常かどうかは分からないが、curlを使わないことが確実なら、上記のコードを次のように変更しておいた方が良い。

  function http($url, $method, $postfields = null) {
/**
      if (function_exists('curl_init')) {
          return $this->httpCurl($url, $method, $postfields);
      }
*/
      return $this->httpNoCurl($url, $method, $postfields);
  }
  
  function httpNoCurl($url, $method, $postfields = null) {
      $headers = array(
              'Content-Type: application/x-www-form-urlencoded',
              'Content-Length: '.strlen($postfields),
      );
      $options = array('http' => array(
              'method' => $method,
              'content' => $postfields,
              'header' => implode("\r\n", $headers),
      ));
      
      $contents = file_get_contents($url, false, stream_context_create($options));
      return $contents;
  }
  
  function httpCurl($url, $method, $postfields = null) {

 実は、このアプリとは別のアプリが正常に機能しなくなって、ログを見たら次のような警告があった。

The Socket API will be enabled for this application once billing has been enabled in the admin console.

 私には意味が分からなかったが、同じ警告が現れた人のブログ記事を見つけた。

GAE/PHPのStandard環境から外部のWeb APIを叩こうとするとInternal Errorになって、ログをみると以下のようなエラーメッセージが記録されていたりする。
(中略)
これはわかりづらいんだけど、
 1. HTTPアクセス時にcurlを使おうとした
 2. curl利用時にはSocket APIを利用するらしい
 3. Socket APIを利用するには課金を有効にしないといけない
ということらしい。
GAE/PHPのStandard環境でHTTPアクセス時にエラー - longkey1's blog

 課金を有効にすれば解決するらしいが、課金を有効にした後に何らかの原因で無料の範囲を超えてしまったら怖い。そこで、既にcurlが使えないことを前提にしたプログラムになっているのだから、その方が良い。
 問題なのは、curlが使えないことを前提にしているのに使っているかのようなエラーが出ることだった。今日の午前8時過ぎに発症したのだが、原因は分からないままである。とりあえず、上記のように対処して、問題は解決したように見える。もしかしたら、GAEの方でバグが解消されたのかもしれないが…。ただ、同じ twitteroauth.php を使っているのに問題が生じたアプリと生じないアプリがある。頭が混乱するトラブルだった。

追記(2017/5/17):

 昨日は問題が無かったアプリでも問題が生じた。 twitteroauth.php を使っている全てのアプリの twitteroauth.php を上記のように書き換えた。


タグ:JSON GAE RSS PHP Twitter
nice!(1)  コメント(0)  トラックバック(0) 
カテゴリー:サイトを見て
共通テーマ:パソコン・インターネット

読者の反応

nice! 1

sonet-asin-area

コメント 0

コメントを書く 

お名前:[必須]
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。
captcha

トラックバック 0

トラックバックの受付は締め切りました

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。