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

A Day In The Boy's Life

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

ずっと、Twitterのリプライってタイミングの合う、合わないで決まるところがあるよね、って思ってたところがあったので、実際に計ってみました。


自分のタイムライン上に流れるリプライの中で時間が計測できるもの(後述)を取得し、元の発言からどれ位の時間でリプライされているのかのデータを取得してみた結果です。

意外と時間がかかっているように思えますが、夜につぶやいたものが朝返ってくる(挨拶系とか)ものもあるため、平均値だとこれぐらいになってしまうのかもしれませんね。



集計対象のデータ


自分のタイムライン上に流れるリプライの時間データを取り込み集計しました。

なので、集計対象のデータには偏りがあるかもしれません。(エンジニア系の人多し)

その中で正確な時間を求めるために、TwitterのAPIから返されるin_reply_to_status_idがあるものをリプライ平均時間の集計対象としました。


総件数で、12,278件ありましたが、うちin_reply_to_status_idがついているものは2,360件でした。

これは、利用しているクライアントによったり、複数の人に対してリプライを返えしたり、RTをするとin_reply_to_status_idが消されるので、そういったデータを対象に含めたら、この平均時間というものは大きく変わってくるかもしれません。

つまりは、1対1のつぶやきのみが対象となっています。



時間帯別のつぶやき、リプライ/RT率など


平均時間だと大きく乖離した時間にデータに影響を受けやすいので、グラフで並べてみました。

先ほども書いたように、このデータにはRTされたデータは含まれていません。


A Day In The Boy's Life-Twitterリプライ分布

やはり、5分以内のreplyが相当多いようです。

30分以内で9割がreplyされるので、逆に言えば30分経過したらreplyもらえる率は格段に悪くなるのかなと思います。

まぁ、「おやすみ」から「おやあり」までの間とかはあると思いますけどね。


次に、時間帯別リプライ、RT数。

0時から23時(X軸)までのどの時間帯にリプライ、RTがされているのかをグラフにしたものです。

これは、RTされたデータも含めています。
A Day In The Boy's Life-Twitter時間帯別
もう少し、時間帯別に差が出るかなと思いましたが9時から0時までではそれほど突出するような時間帯はないようですね。

21時以降にやり取りが増えるのはTwitter夜の部ってことでしょうか(笑


最後にRT率。
A Day In The Boy's Life-Twitterリプライ率

半分以上がRTを使うという結果に。

タイムライン眺めてても経験値としてそう感じますけど。



取得したPHPスクリプト


元ネタは「Twitterのタイムラインを取得するPHPスクリプト 」でかいたPHPスクリプトです。

実際には、後で集計しやすいように取得したデータをDBに格納しています。

また、3分おきにデータを取得するようにCronに登録して動かしました。


別の角度から集計してデータを眺めてみたら面白い発見があるかもしれません。


<?php

require_once "HTTP/Client.php";

$username = "xxxxx";
$password = "xxxxx";
$page = "statuses/friends_timeline.xml" . $status;

$basic = array('Authorization'=>'Basic '.base64_encode($username.':'.$password));

$client = new HTTP_Client(null, $basic);
$client->get("http://twitter.com/".$page );
$response = $client->currentResponse();
$body = mb_convert_encoding($response['body'], "EUC-JP","auto");

$xml1 = new SimpleXMLElement($body);

// 取得したデータを解析
// tid  : 発言元のステータスID
// ttime: 発言元のPOSTした時間
// fid  : replyのステータスID
// ftime: replyした時間

for ($i = 0; $i < count($xml1->status); $i++) {

    $matches = array();

// つぶやき内のユーザー名の数を取り出し
    $match_cnt = preg_match_all("/@[a-zA-Z0-9_:]*/", $xml1->status[$i]->text, $matches);

// RTされた場合
    if ((preg_match("/RT[:]* /", $xml1->status[$i]->text) && ($match_cnt > 0))) {

        $fid   = $xml1->status[$i]->id;
        $ftime = "'" . date('Y/m/d H:i:s', strtotime($xml1->status[$i]->created_at)) . "'"
;

        if ($xml1->status[$i]->in_reply_to_status_id != "") {
            $page = "statuses/show/" . $xml1->status[$i]->in_reply_to_status_id . ".xml";
            $client->get("http://twitter.com/".$page );
            $response = $client->currentResponse();
            $body = mb_convert_encoding($response['body'], "EUC-JP","auto");

            $xml2 = new SimpleXMLElement($body);
            $tid   = $xml2->id;
            $ttime = "'" . date('Y/m/d H:i:s', strtotime($xml2->created_at)) . "'";
        } else {
            $tid   = "null";
            $ttime = "null";
        }
    } else {
// 通常のreply
        if ($match_cnt === 1) {

// あて先がはっきりしているreply
            if ($xml1->status[$i]->in_reply_to_status_id != "") {

                $page = "statuses/show/" . $xml1->status[$i]->in_reply_to_status_id . ".xm
l";
                $client->get("http://twitter.com/".$page );
                $response = $client->currentResponse();
                $body = mb_convert_encoding($response['body'], "EUC-JP","auto");

                $xml2 = new SimpleXMLElement($body);
                $tid   = $xml2->id;
                $ttime = "'" . date('Y/m/d H:i:s', strtotime($xml2->created_at)) . "'";
                $fid   = $xml1->status[$i]->id;
                $ftime = "'" . date('Y/m/d H:i:s', strtotime($xml1->status[$i]->created_at
)) . "'";
            } else {
// 1人宛だがin_reply_toオプションが無いクライアントでreplyを返した場合
                $insert_flg = TRUE;

                $tid   = "null";
                $ttime = "null";
                $fid   = $xml1->status[$i]->id;
                $ftime = "'" . date('Y/m/d H:i:s', strtotime($xml1->status[$i]->created_at
)) . "'";
            }
        } elseif ($match_cnt > 1) {
// 複数宛のreplyの場合

              $tid   = "null";
            $ttime = "null";
            $fid   = $xml1->status[$i]->id;
            $ftime = "'" . date('Y/m/d H:i:s', strtotime($xml1->status[$i]->created_at)) .
 "'";
        }
    }
}

?>



Wikiは決まった作法で文章を書くとHTMLに変換してくれ、HTML言語を知らなくてもWeb上に装飾した文章で表現することができます。

最近は、Wikiエンジンを搭載したツールも多かったりしますが、そういったものを使ったときには使い方が固定されるところもあるので、自分の考えていた用途で使えないという場合もあります。

例えば、Wikipediaで使われているMediaWikiを使うと、Wikipedia同等のものを導入することができますが、あそこまで大規模な文章管理の仕組みは必要なかったり、ユーザー管理が弱かったりもしますので社内で使いづらい、なんて場合もあります。


PEARのText_WikiはそのWikiエンジンの部分だけを提供してくれますので、オリジナルのシステムに導入することができ、色んな用途で使うことも可能になります。



Text_Wikiを導入する


これは、一般的なPEARパッケージのインストールと同様なのであまり詳しく書きません。

ネットワークやチャンネルの設定が終っていれば、


$ pear install Text_Wiki

でいけるかもしれません。



Text_Wikiを使ってみる


基本的な使い方であれば、下記のように書くことでWiki文法の文章をHTMLに変換してくれます。


<?php

require_once "Text/Wiki.php";

$wiki = new Text_Wiki();

// Wiki文法で書かれた文章をXhtmlに変換する
$wiki->setFormatConf('Xhtml', 'translate', HTML_SPECIALCHARS);

// Wiki文法で書いた文章
$text = "これは、**''Text_Wiki''**で書かれたものです。";

// 変換
echo $wiki->transform($text, 'xhtml');

?>

$ php wiki.php
<p>これは、<strong><i>Text_Wiki</i></strong>で書かれたものです。</p>


wiki.php内の$textに代入している文章の中にWiki文法が使われています。

「** XXXX **」のフォーマットで書くと強調表示(<strong>タグ)に、「'' XXXX ''」のフォーマットで書くと斜体(<i>タグ)に変換されます。

setFormatConf()では、Wiki文法をXhtmlに変換するように設定するものです。


Text_WikiのWiki文法は、WikkiTikkiTavicoWiki の文法を組み合わせているようです。

使えるWiki文法の詳細は、マニュアルページ に書かれています。



Wiki文法をカスタマイズする


オリジナルのWikiエンジンを作るということなので、その文法を改変するということもできます。

まずは、既定のルールを無効にしています。


先ほどの、wiki.phpのサンプル内で使われていた斜体にするWiki文法(''で囲む)を無効にしてみます。


// 斜体のWiki文法を削除
$wiki->deleterule('italic');

// Wiki文法で書いた文章
$text="これは、**''Text_Wiki''**で書かれたものです。";

$ php wiki.php
<p>これは、<strong>''Text_Wiki''</strong>で書かれたものです。</p>


斜体のWiki文法が無効になっていますね。

予め定義されているルールは、マニュアルのページのルールの一覧 に書かれています。

次に、Wiki文法をオリジナルの書き方に変更してみます。

デフォルトで、強調表示するWiki文法である「** XXXX **」という書き方を、「@@@ XXXX @@@」という表現に変えてみます。


まず、Text_Wikiの各種パーサがまとめられたディレクトリ内に、オリジナルのWiki文法用のものを定義します。


$ cd /path/to/pear/Text/Wiki/Parse/Default

$ ls
Anchor.php      Delimiter.php  Image.php      Prefilter.php    Tighten.php
Blockquote.php  Embed.php      Include.php    Raw.php          Toc.php
Bold.php        Emphasis.php   Interwiki.php  Revise.php       Tt.php
Break.php       Freelink.php   Italic.php     Smiley.php       Underline.php
Center.php      Function.php   List.php       Strong.php       Url.php
Code.php        Heading.php    Newline.php    Subscript.php    Wikilink.php
Colortext.php   Horiz.php      Paragraph.php  Superscript.php
Deflist.php     Html.php       Phplookup.php  Table.php

この中には、Wiki文法1つにつき、1ファイルが置かれています。

テンプレとして使えるので、ここではまず元々あるStrong.phpをコピーしてCustomstrong.phpファイルを作ります。


次に、ファイルを開いてClass名を命名規則に沿って「Text_Wiki_Parse_Customstrong」に変更した後、Wiki文法のフォーマットを作ります。


var $regex =  "/@@@(.*?)@@@/";

次に、HTML構文に変換する役割を持つファイルを作ります。

これは、先ほどのディレクトリとは異なる場所に定義されています。

$ cd /path/to/pear/Text/Wiki/Render/Xhtml

この中には、先ほどのParseディレクトリ内のファイルと1対1の関係でファイルが置かれています。

なので、同様にStrong.phpファイルをコピーしてCustomstrong.phpとし、Class名を「Text_Wiki_Render_Xhtml_Customstrong」としておきましょう。


これで準備が整ったので、先ほどのwiki.phpを使って動作確認をしてみましょう。

新しいルールを適用するに当たって、insertRule()という関数を使って、先ほどのルールを使用できるようにしています。


$wiki->insertRule('Customstrong');

// Wiki文法で書いた文章
$text="これは、@@@Text_Wiki@@@で書かれたものです。";

$ php wiki.php
<p>これは、<strong>Text_Wiki</strong>で書かれたものです。</p>


ちなみに、このままだと元々の強調表現である「** XXXX **」という文法も使えるため、下記のように書いてルールを置き換えてしまうこともできます。


$wiki->changeRule('Strong', 'Customstrong');

// Wiki文法で書いた文章
$text="これは、@@@Text_Wiki@@@で**書かれた**ものです。";

$ php wiki.php
<p>これは、<strong>Text_Wiki</strong>で**書かれた**ものです。</p>


その他にもHTMLタグに変換した際にCSSを適用させることもできます。


$conf = array(
    'css_table' => 'my_table_class',
    'css_tr' => 'my_tr_class',
    'css_td' => 'my_td_class'
);

$wiki->setRenderConf('Xhtml', 'Table', $conf);

$text="|| テーブル ||";

$ php wiki.php
<table class="my_table_class">
    <tr class="my_tr_class">
        <td class="my_td_class">テーブル</td>
    </tr>
</table>


Text_Wikiを使って色々な形式にカスタマイズし、オリジナルのWikiエンジンを作り出したり、既存のWikiエンジンの文法を取り入れることも可能です。

既存のWikiエンジンの文法を取り入れたい場合、カスタマイズするよりText_Wikiをベースに作られたText_Wiki_Mediawiki (MediaWikiの文法を取り入れたもの)もあるようなので、そっちを使ってみるのも良いかもしれません。




最近、ブログに変わる情報発信ツールとしてTwitterが注目を浴びる一方で、そういえばRSSはどうなった?ってふと思ったりしました。

ブログの台頭とともにRSSも栄えていきましたが、Twitterの勢力が増しブログが衰退していくと、RSSも同様に死んでいく運命にあるのかな、と思ったりします。



情報はPull型からPush型へ?


RSSが出てきた頃は、メールに変わるコミュニケーションのインフラとして期待されていて、これからの情報は誰かに投げつけるPush型ではなく、自分から取りに良くPull型だ!見たいなことが騒がれていました。

Twitterの勃興によりブログは死んだ、見たいな事を言われだすと、そのRSSの存在価値も薄れていっているのかな、と思ったりします。


Twitterでの情報のやり取りを見ていると、情報を引き出すというよりは、自ら置きにいっている感覚です。

メールなんかのように(どちらかというとTwitterという巨大なメーリングリストのよう)、誰彼と無くつぶやいたり、特定の誰かにreplyを投げたりしています。


自ら情報をとりに良くというスタイルは、ITを駆使する人にとっては当たり前のことに感じますが、実際は沢山の釣り糸をたらして情報を待つスタイルでもあります。

釣れないときは退屈で、釣れたとしてもそれが狙ってた獲物であるとも限らなかったりします。

自分も多くのブログをリーダーで購読していますが、未読件数が溜まっても実際に読むのはその中の本の一握りだったりもします。


Pull型のコミュニケーションは、そこに自分の興味の対象がある場合、それを引き出すことに面白さを感じたりもしますが、そうでない場合や情報があがってこなかったら退屈になってしまいますし、これだけブログというものが浸透して、ネットが混沌としてくると情報を釣っていくことにも限界が来るところがあります。


面白いものを見つけたいなら、じっと待つよりピンポイントにこの情報というものを引き出したくなってくるのかなと。



やっぱりコミュニケーションに頼るのは人なのか?


人力検索のようなサービスも流行っていますが、Twitterでの情報のやり取りを見ていると、やっぱりシステムなんかに頼るより、人に頼った方が現時点で最も効率がいいと感じたりします。

(もちろんそれを支えるのはシステムですけど)


なので、Twitterの凄さはそれを支えるインフラがあることはもちろんなのですが、どちらかというとその中の人が凄いんだな、と感じたりします。

これが知りたい!といったときに誰かが答えてくれる。

情報のタネをまくと、どこからと無く水遣りが始まって花が咲き出すわけです。


RSSは、基本的に何が釣れるかわからない状態であるのに対し、TwitterのようなPush型のコミュニケーションを取ると、求めてたものに近いものが得られます。

ブログは、書き手というよりその空間がメインになりますし、そこで得られる情報はある程度専門特化されます。

それは、Twitterよりも得られる情報の濃度が高いという特徴もあるかもしれませんが、一方でその専門は範囲が狭いことも考えられ、複数のRSSを購読しなければならないというような事態にもなります。


Twitterは人の寄せ集めで成り立っていますから、専門特化されることが少ない。

(フォローする人を調整すれば可能かもしれませんけど)

誰かに聞けば何か知ってるだろう、という感覚がありますしね。


ただ、Twitterは情報の受け皿が必要になるので、少なくともそれだけで完結することは少ないかなと思います。

なので、ブログの存在が完全に消えることはもちろん無いでしょうし、どちらかというとブログの中で行われている短期間で行うコミュニケーションがTwitterのようなマイクロブログに吸収されていくのではないかなと思ったりします。


そして、Twitterの中の人にその存在を効率的に示すための手段が必要になります。

現時点で、それはRSSが担っていますが、例えばその更新情報がTwitterのような領域にどんどん流れていきだすと、ますますRSSの活用の場というのは少なくなっていくのかもしれません。