A Day In The Boy's Life -88ページ目

A Day In The Boy's Life

とあるエンジニアのとある1日のつぶやき。

このアメーバブログに設置していたツイート(つぶやく)ボタンですが、過去の経緯を辿れば「Amebaブログに「Twitterへ投稿ボタン」を設置してみたよ 」で独自のツイートボタンを実装し、その後Twitter界隈でつぶやかれた数も取得できるということで「ReTweet数を表示できるTopsyブログパーツをAmebloに張ってみたよ 」で、Topsyに切り替えたのですが、ここ数日Topsyのリツイートボタンをクリックするとエラーが表示(※1)されるようになり、対処がめんどくさくなった(おぃ)ので、Twitter公式のツイートボタンに切り替えることにしました。


ってことで、Twitter公式のツイートボタンをAmebloに設置する方法を紹介します。



Twitter公式のツイートボタンを設置するためのJavaScriptコードを取得


まず、Twitterのツイートボタン作成ページ からボタンを設置するためのJavaScriptのコードを取得します。


1. ボタンを選択してください。カスタマイズすることもできます。」のボタンの配置はお好みのものを選択しましょう。

ツイート内テキストは、「ボタンが表示されるページのタイトル。」を選択、URLもデフォルトで選択されている「ボタンが表示されるページのURL」を選択しておきます。

これは後述するカスタマイズで、トップページやエントリ一覧ページからもボタンを設置したエントリに対して正しくツイートを作り出すためです。


言語選択もお好みのもので問題ありません。

日本語だと「ツイートする」と表示され若干ボタンが長くなったので、このブログでは「英語」を選択したものを貼り付けています。


2. フォローするのにおすすめのユーザー(オプション)」は、ブランクでもかまいませんが自分のアカウント名を入れておけば、ボタンクリックした際に「via @it_boy」のように表示され、そのまま投稿されればリプライも同時に受け取ることができます。


これだけで準備が整ったので、右下のJavaScriptのコードをコピーしておきます。



Amebaブログにツイートボタンを設置するためのJavaScript


半ばテンプレ化してしまっていますが、「Amebaブログに「Twitterへ投稿ボタン」を設置してみたよ 」で書いたjQueryのコードにて、先ほど取得した公式ツイートボタンのJavaScriptをエントリの内に埋め込みます。


下記のJavaScriptコードをAmeblo管理ページのフリープラグイン(ブログを書く > サイドバー設定 > フリープラグイン)の適当な位置に入力します。


注意)

下記のコードをそのまま貼り付けると、このブログのタイトルや私のTwitterID(@it_boy)が表示されます。

後述の編集箇所を参考に、自分自身のブログのタイトルやTwitterIDに修正してください。


<script>
$(document).ready(function(){
  var page_url = location.href;
  if (page_url.match(/^.+\/entrylist[\-0-9]*\.html$/g )) {
    var entries = $(".newentrytitle a");
    var classname = ".updatetime";
    var flg = 0;
  } else {
    var entries = $(".foot a:contains('記事URL')");
    var classname = "div.entry .theme";
    var flg = 1;
  }
  for (i = 0; i < entries.length; i++) {
    var url = entries[i];
    if (flg == 0) {
      title = entries.eq(i).text();
    } else {
      title = $("div.entry h3.title").eq(i).text();
    }
    var twit_url = '<a href="http://twitter.com/share" class="twitter-share-button" data-count="horizontal" data-via="it_boy" data-text="' + title + ' | A Day In The Boy&#39;s Life" data-url="' + url + '">Tweet</a>';
    var twitter_btn = twit_url + '<sc' + 'ript type="text/javascript" src="http://platform.twitter.com/widgets.js"></sc' + 'ript>';
    $(classname).eq(i).append('&nbsp;&nbsp;' + twitter_btn);
  }

})
</script>


その後、一部カスタマイズが必要になります。

まず、先ほどTwitterサイト上で取得したJavaScriptコードの中からアンカータグの部分(<a href=" ~ </a>)だけを下記の変数の箇所に埋め込みます


※ jQueryの仕様上、SCRIPTタグをそのまま変数に入れることができず、区切って書く必要があるのですが、その説明を簡略化するためにあえて別の変数で定義してます。


var twit_url = '<a href="http://twitter.com/share" class="twitter-share-button" data-count="horizontal" data-via="it_boy" data-text="' + title + ' | A Day In The Boy&#39;s Life" data-url="' + url + '">Tweet</a>';


次に、上記のアンカータグ内に2つのプロパティを追加します。


data-text="' + title + ' | 自分のブログ名"

data-url="' + url + '"

title変数には、各エントリのタイトルが入っているので、トップページを表示した場合でも、そのタイトルをきちんとツイート内に表示できるようにしています。

タイトルは、自分のブログ名に編集してください。

同様に、url変数には各エントリのパーマネントリンクが入っています。

これで、フリープラグインを保存すればタイトル下の日付の横にツイートボタンが表示されているかと思います。


- 公式ツイートボタンをクリックしたときの例

A Day In The Boy&#39;s Life-Twitter公式ツイートボタン


使って少ししか経過していませんが、Topsyのものと比べリツイート(Twitterへ投稿された)数がだいぶ少なく表示されるようです。

まだ始まったばかりのサービスですし、全データをうまくクロールしきれていないせいかもしれません。

時間の経過とともに修正されていくかわかりませんが、公式のものですし今後はより正確な数値が表示されていくようになると思います。(期待も込めて)



※1 リツイートボタンをクリックすると下記のようなメッセージが表示される。


Error
Caught exception in Otter::Controller::Concept->retweet "Malformed UTF-8 character (fatal) at /opt/perl/lib/vendor_perl/5.12.1/x86_64-linux/XML/LibXML/Error.pm line 217. at /opt/lighttpd/otter.master.26493.e11c189ccf/otter/script/../../lib/UB/Agent/LWP.pm line 236"




前回、「OAuthを使ってPHPからTwitterへ投稿する 」にて、PHPからOAuthを使うための環境準備とTwitterへつぶやきを投稿するプログラムを書いてみましたが、今回はタイムラインから様々な情報を取得するPHPプログラムを書いてみます。



共通系処理の準備


OAuth認証系の処理については、基本的に前回書いたプログラムと同様です。

ここはタイムラインの操作でも共通する処理になるため、切り出して別のプログラムファイルとして定義しておきます。


<?php

include 'HTTP/OAuth/Consumer.php';

$consumer_key    = 'アプリ登録した際のコンシューマーキー';
$consumer_secret = 'アプリ登録した際のコンシューマーシークレットキー';

$access_token        = 'アプリに対して発行したアクセストークン';
$access_token_secret = 'アプリに対して発行したアクセストークンシークレット';

$consumer = new HTTP_OAuth_Consumer($consumer_key, $consumer_secret);

$http_request = new HTTP_Request2();
$http_request->setConfig('ssl_verify_peer', false);
$consumer_request = new HTTP_OAuth_Consumer_Request;
$consumer_request->accept($http_request);
$consumer->accept($consumer_request);

// リクエストトークンの発行を依頼
$consumer->getRequestToken('https://twitter.com/oauth/request_token');

// リクエストトークンを取得
$request_token = $consumer->getToken();
$request_token_secret = $consumer->getTokenSecret();

// リクエストトークンをセット
$consumer->setToken($request_token);
$consumer->setTokenSecret($request_token_secret);

// 発行済みのアクセストークンをセット
$consumer->setToken($access_token);
$consumer->setTokenSecret($access_token_secret);


上記の処理でOAuthの認証がクリアされているので、後はTwitterのAPIを以降書いていくことで様々な操作をすることができます。



タイムラインからツイートを取得する


まずは、パブリックタイムラインからつぶやきの情報を取得してみます。


<?php

include 'oauth.php';

$api_url = "http://api.twitter.com/1/statuses/public_timeline.xml";
$result = $consumer->sendRequest($api_url, array(), "GET");

$xml = new SimpleXMLElement($result->getBody());

for ($i = 0; $i < count($xml->status); $i++) {
    echo $xml->status[$i]->user->screen_name . " : " . date('Y/m/d H:i:s', strtotime($xml->status[$i]->created_at)) . "\n";
    echo "\t" . $xml->status[$i]->text . " / " . $xml->status[$i]->id . "\n";
}


$api_urlで指定しているのが、パブリックタイムラインから情報を取得するためのAPI用URLです。

後半の処理は、XMLで情報を取得したため、それを解析して端末上に出力するようにしています。

出力の形式は


スクリーン名 : 投稿日時

          ツイート(つぶやき本文) / ツイートのID


としています。

お次は、ユーザータイムラインから自分のつぶやきだけを取得してみます。


<?php

include 'oauth.php';

$param["screen_name"] = "it_boy";
$api_url = "http://api.twitter.com/1/statuses/user_timeline.xml";
$result = $consumer->sendRequest($api_url, $param, "GET");

$xml = new SimpleXMLElement($result->getBody());

for ($i = 0; $i < count($xml->status); $i++) {
    echo $xml->status[$i]->user->screen_name . " : " . date('Y/m/d H:i:s', strtotime($xml->status[$i]->created_at)) . "\n";
    echo "\t" . $xml->status[$i]->text . " / " . $xml->status[$i]->id . "\n";
}


プログラムの内容自体はほとんど同一ですが、$paramでAPIに送信するパラメータを指定しています。

誰のユーザータイムラインを見るかってところで、screen_name(スクリーン名)を指定してタイムラインの情報を拾っています。

ユーザーIDを使って取得することも可能です。

また、その他のAPI操作でも色々なパラメータを指定して情報を操作することができますが、上記のようにパラメータを指定しておけばAPI側にその情報を送ることができます。


余談ですが、パブリックタイムラインとユーザータイムラインの情報はOAuth認証なしでも情報を取得することができます。

認証なしといっても、コンシューマーキーとリクエストトークンをセットした上でAPIにアクセスしなくてはなりませんが。

そうしたい場合は、下記のようにアクセストークンなしで認証を通過させ、APIへアクセスします。


<?php

include 'HTTP/OAuth/Consumer.php';

$consumer_key    = 'アプリ登録した際のコンシューマーキー';
$consumer_secret = 'アプリ登録した際のコンシューマーシークレットキー';

$consumer = new HTTP_OAuth_Consumer($consumer_key, $consumer_secret);

$http_request = new HTTP_Request2();
$http_request->setConfig('ssl_verify_peer', false);
$consumer_request = new HTTP_OAuth_Consumer_Request;
$consumer_request->accept($http_request);
$consumer->accept($consumer_request);

// リクエストトークンの発行を依頼
$consumer->getRequestToken('https://twitter.com/oauth/request_token');

// リクエストトークンを取得
$request_token = $consumer->getToken();
$request_token_secret = $consumer->getTokenSecret();

// リクエストトークンをセット
$consumer->setToken($request_token);
$consumer->setTokenSecret($request_token_secret);


もちろんアクセストークンつきでも問題なく情報は取得できますので、あえて分離するメリットはないかと思いますが・・・。


次は、ホームタイムラインからの情報取得です。

これは、自分がTwitterへログインしたときと同じ情報を取得することができます。

プログラムは、パブリックタイムラインを取得するプログラム(public_timeline.php)内の$api_urlを下記に書き換えるだけで取得できます。


$api_url = "http://api.twitter.com/1/statuses/home_timeline.xml";


似たような情報として、friends_timelineというAPIもあるのですが、こちらは公式リツイートの情報が取得できません。

また、古いAPIで将来廃止の予定らしいので、home_timelineのAPIを使ってた方がよいでしょう。


タイムライン系最後は、自分宛の返信の情報を取得してみます。

こちらも、先ほど同様に$api_urlを変更するだけで自分に返信したつぶやきの情報を取得することができます。


$api_url = "http://api.twitter.com/1/statuses/mentions.xml";

各APIの詳細は、公式のAPIドキュメント も参照してみてください。


リツイート系の情報を取得する


次は、リツイート系の情報を拾ってみます。


※ リツイートは全て公式のものです。単に発言にRTつけて返信したものは含まれません。


これには、3つのAPIが用意されています。

ただ、PHPのプログラム自体は先ほど同様に全て$api_urlの部分を書き換えるだけで動作します。


- 自分のタイムライン上でリツイートされたつぶやきを取得する


自分が閲覧可能なタイムラインの中で公式リツイートされた情報だけを取得します。


$api_url = "http://api.twitter.com/1/statuses/retweeted_to_me.xml";

- 自分がリツイートしたつぶやきを取得する


自分が公式リツイートしたつぶやきの一覧を取得します。


$api_url = "http://api.twitter.com/1/statuses/retweeted_by_me.xml";

- 自分の発言の中でリツイートされたものを取得する


最後は、自分の発言が公式リツイートされたものを取得します。


$api_url = "http://api.twitter.com/1/statuses/retweeted_of_me.xml";




8月末でBasic認証でのAPI操作が終了になるってことで、かなりぎりぎりですがOAuthを使ってPHPのプログラムからTwitterへ投稿するプログラムを書いてみました。


OAuthを通してのTwitterの操作は、PEARのService_Twitter を使えばかなり楽そうなんですが、借りてるサーバーのPHPがバージョン5.1.6でして・・・。

ってことで、同じPEARのHTTP_OAuth を利用することにしました。

ちなみに、レンタルサーバーはファーストサーバ を使ってます。


ここで書いているものは、bot用のものなのでウェブアプリケーションを作りたい場合は、多少異なってきます。



PEARパッケージHTTP_OAuthをインストールする


pearコマンドを使ってインストールできますが、私の環境では幾つかパッケージが足りなかったりしたので、以下その作業ログです。


# pear install HTTP_OAuth-alpha
Did not download optional dependencies: pear/Log, pecl/pecl_http, use --alldeps to download automatically
pear/HTTP_OAuth can optionally use package "pear/Log" (version >= 1.11.0)
pear/HTTP_OAuth can optionally use package "pecl/pecl_http" (version >= 1.6.0)
pear/HTTP_Request2 requires PEAR Installer (version >= 1.5.4), installed version is 1.4.9
pear/HTTP_Request2 can optionally use PHP extension "fileinfo"
pear/HTTP_OAuth requires package "pear/HTTP_Request2" (version >= 0.4.0)
No valid packages found
install failed

HTTP_OAuthに必要なパッケージがもろもろないよといわれたので、関連するパッケージをまとめてインストールする。

まずは、pecl_httpをインストール。


# pecl install pecl_http

install ok: channel://pecl.php.net/pecl_http-1.6.6
You should add "extension=http.so" to php.ini

インストール後は、メッセージにあるようにphp.iniに「extension=http.so」を追加。

つぎに、PEAR本体をアップグレード。


# pear upgrade PEAR
pear/Archive_Tar requires PEAR Installer (version >= 1.5.4), installed version is 1.4.9
pear/PEAR dependency package "pear/Archive_Tar" installed version 1.3.2 is not the recommended version 1.3.7, but may be compatible, use --force to install
No valid packages found
upgrade failed


単にupgradeオプションを指定してもバージョンアップできなかったので、forceオプション付けて無理やりアップグレード。


# pear upgrade --force PEAR
warning: pear/Archive_Tar requires PEAR Installer (version >= 1.5.4), installed version is 1.4.9
downloading PEAR-1.9.1.tgz ...
Starting to download PEAR-1.9.1.tgz (293,587 bytes)
.............................................................done: 293,587 bytes
downloading Archive_Tar-1.3.7.tgz ...
Starting to download Archive_Tar-1.3.7.tgz (17,610 bytes)
...done: 17,610 bytes
upgrade ok: channel://pear.php.net/Archive_Tar-1.3.7
upgrade failed

Archive_Tarがエラーはいてるけど無視で・・・。
とりあえずPEAR本体はアップグレードできたっぽい。
この状態で再チャレンジ。


# pear install HTTP_OAuth-alpha
pear/HTTP_Request2 can optionally use PHP extension "fileinfo"
downloading HTTP_OAuth-0.1.14.tgz ...
Starting to download HTTP_OAuth-0.1.14.tgz (50,901 bytes)
.............done: 50,901 bytes
downloading HTTP_Request2-0.5.2.tgz ...
Starting to download HTTP_Request2-0.5.2.tgz (58,159 bytes)
...done: 58,159 bytes
install ok: channel://pear.php.net/HTTP_Request2-0.5.2
install ok: channel://pear.php.net/HTTP_OAuth-0.1.14

ということで、なんとかHTTP_OAuthをインストールすることができました。



Twitterアプリの登録


次は、OAuth認証できるようにTwitterアプリを登録します。

Twitterにログインした状態で、dev.twitter.com のサイトへアクセスします。


※ 普段利用するtwitter.comのサイトからもアプリケーション登録はできます(設定>連携アプリ)が、その後のアクセストークンの取得ができないため、dev.twitter.comからアプリケーション登録した方が早いです。(紛らわしいですがね)


アクセス後、上部にある「Your Apps」メニューを開き、右側にある「新しいアプリケーションを登録する」をクリックします。


アプリケーション名 その名の通りアプリケーションの名前。投稿した場合に発言内容の下に表示(※)される。
アプリケーションの説明 アプリケーションの概要などを書いておいます。必須項目なので適当に入力しておきましょう。
アプリケーションのウェブサイトURL アプリケーション名をクリックしたときにそのサイトが表示されます。
所属会社/団体 会社名や組織名などを書くんでしょうが、必須項目ではないのでブランクでも可。
アプリケーションの種類 PCなどにインストールして使うソフトウェアやbotの場合は「クライアントアプリケーション」を、ウェブサービスにOAuthを利用してログインさせるといった場合は「ブラウザアプリケーション」を選択します。今回は、botプログラムを作るので「クライアントアプリケーションを選択しておきます。
Default Access Type アプリが読み込み専用か、読み書きできるようにするか。今回は書き込むのでRead & Writeを選択。
アプリケーションのアイコン 専用のアイコンを使いたいなら登録しておきましょう。

※ 下記の部分に表示されます。


A Day In The Boy&#39;s Life-TwitterApps登録


入力が終わったら「アプリケーションを保存」ボタンをクリックし、登録完了です。


アプリの登録が完了したら、アプリケーションの一覧画面へ戻り、先ほど作ったアプリ名をクリックして詳細画面を開きます。

この中に、「Consumer key」と「Consumer secret」のキーが表示されているので、まずはそれをメモします。

その後、右メニューに「My Access Token」というメニューがあるのでクリックし、「Access Token (oauth_token)」と「Access Token Secret (oauth_token_secret)」のキーもメモっておきます。

以上で、bot用アプリケーションの準備は完了です。



OAuthの流れを簡単に見てみる


プログラムを早速作りたいところではありますが、簡単にOAuthの流れを見ておきます。

詳細は、下記のエントリがとてもわかりやすいです。


OAuthプロトコルの中身をざっくり解説してみるよ @ ゆろよろ日記


botプログラムを作る場合は、ユーザーとコンシューマーが同一になります。

また、botプログラムになるので認証要URLへリダイレクトされることもありません。

ここで、ユーザーがコンシューマーに対してアクセス許可をするとアクセストークンが発行されますが、botの場合は同一なのでこの作業フロー自体がありません。

アクセストークンの取得自体は、先ほど「My Access Token」のメニューからメモったものを利用するので、すでに取得済みの状態となります。


簡単に流れを書くと


1. コンシューマー(bot)がプロバイダ(Twitter)に対して、コンシューマーキーを利用してリクエストトークンの発行を依頼

2. 1.で取得したリクエストトークンとアクセストークンをセットしてOAuth認証を行う

3. OAuthを通してTwitter APIを利用する


という流れです。



PHPからTwitterへ投稿するスクリプト


ということで、プログラム本体。


<?php

include 'HTTP/OAuth/Consumer.php';

$consumer_key    = 'アプリ登録した際のコンシューマーキー';
$consumer_secret = 'アプリ登録した際のコンシューマーシークレットキー';

$access_token        = 'アプリに対して発行したアクセストークン';
$access_token_secret = 'アプリに対して発行したアクセストークンシークレット';

$http_request = new HTTP_Request2();
$http_request->setConfig('ssl_verify_peer', false);

$consumer = new HTTP_OAuth_Consumer($consumer_key, $consumer_secret);
$consumer_request = new HTTP_OAuth_Consumer_Request;
$consumer_request->accept($http_request);
$consumer->accept($consumer_request);

// リクエストトークンの発行を依頼
$consumer->getRequestToken('https://twitter.com/oauth/request_token');

// リクエストトークンを取得
$request_token = $consumer->getToken();
$request_token_secret = $consumer->getTokenSecret();

// リクエストトークンをセット
$consumer->setToken($request_token);
$consumer->setTokenSecret($request_token_secret);

// 発行済みのアクセストークンをセット
$consumer->setToken($access_token);
$consumer->setTokenSecret($access_token_secret);

// 投稿したい内容(文字コードはUTF-8で)
$tweet = mb_convert_encoding('テスト', 'UTF-8');

// OAuthを利用してTwitterの投稿APIへつぶやきを投げる
$response = $consumer->sendRequest('http://api.twitter.com/1/statuses/update.xml', array('status' => $tweet), 'POST');

// 投稿した結果を取得
echo $response->getBody();


投稿が成功したらステータスがXML形式で返ってきます。


<?xml version="1.0" encoding="UTF-8"?>
<status>
  <created_at>Sat Aug 21 15:49:32 +0000 2010</created_at>
  <id>21758423140</id>
  <text>&#12486;&#12473;&#12488;</text>
  <source>&lt;a href=&quot;http://ameblo.jp/itboy/&quot; rel=&quot;nofollow&quot;&gt;itbot&lt;/a&gt;</source>
  <truncated>false</truncated>
  <in_reply_to_status_id></in_reply_to_status_id>
  <in_reply_to_user_id></in_reply_to_user_id>
  <favorited>false</favorited>
  <in_reply_to_screen_name></in_reply_to_screen_name>
  <retweet_count></retweet_count>
  <retweeted>false</retweeted>
- snip -

投稿がうまくいかない場合は、下記のようなエラーメッセージがXML形式で返ってきたりします。


- メッセージその一

<?xml version="1.0" encoding="UTF-8"?>
<hash>
  <request>/1/statuses/update.xml</request>
  <error>Incorrect signature</error>
</hash>

ググってみたら、文字コードが正しくない場合にでるとかありますが、私の場合は単にコンシューマーキーが間違ったものを指定していました。

アクセストークンやリクエストトークンの指定方法が間違っていても同様に出るかもしれません。


- メッセージその二

<?xml version="1.0" encoding="UTF-8"?>
<hash>
  <request>/1/statuses/update.xml</request>
  <error>Status is a duplicate.</error>
</hash>

前回と同様の内容を投稿しようとした場合に返ってくるメッセージです。

テスト投稿する場合は、同一の内容で何度もPOSTしたいんですが、Twitterの制限なので毎回違う内容で試してみてください。


- メッセージその三

<?xml version="1.0" encoding="UTF-8"?>
<hash>
  <request>/1/statuses/update.xml</request>
  <error>Invalid Unicode value in one or more parameters</error>
</hash>

投稿する文字列がUTF-8以外のものを指定した場合にでました。

私の環境だとPHPの内部エンコーディングがEUC-JPだったので、そのまま投稿しようとした場合に文字化けしたり、上記のメッセージが返ってきたりしました。



結構苦労しましたが、これでどうにか8月以降もTwitter APIをいじいじできそうです。。