Twitterの発言アーカイブ

Twitterでは、自分の発言は3200ポストまでしか取得できません。(多分、溜め込んでいるとは思うけど、取得する術がない。)

でも、自分でアウトプットした情報は、日記として読み返したり、メモ代わりにつぶやいた情報を後で検索したりしたいのです。そこで、前回の日記で書いたアーカイブ方法でバックアップを取っています。

LoudTwittertwtr2srcでは、はてなダイアリーに送りつけていますが、これには一つ問題があります。

はてなダイアリーに限らず、ほとんどのブログ系サービスには容量に限界がありますし、サービス自体の存続も保証されません。私の場合、公開が主目的ではないので、どうせメールでブログ更新するなら、直接自分にメールを送ってもいいのですが、味気ないのでGoogle Readerでブログのフィードを取得して、二重でバックアップするようにしています。

現在、twtr2srcの不具合時バックアップとして、Twitterのプロファイルページのフィードも購読していますが、こちらはやめようと思います。1発言1記事なので、記事数が嵩張って邪魔なのです。

一点怖いのは、Google Readerの仕様です。今のところ古い記事も溜め込んでいますが、いつ古い情報が切り落とされるのか分かりません。そう考えると、メールで取っておいた方がいいのかな、などと悩んでいるところです。

LoudTwitterに変わるもの

LoudTwitterの存続が怪しいので、自前で用意してみた。

9/4追記:復活しましたね。一安心。絶賛ドネーション受付中です。でもtwtr2srcに移行しました。まだβですが全く問題ありません。類似サービスとして、t2bとか、専用サイトまで用意してくれるTwilogなどもあります。

仕様や注意点

取得結果をメール送信するので、自分宛に送ってもいいし、はてダに送ってもいい。
手抜き仕様として、200件しか取得しません。一日200件以上発言する人はページング処理など追加する必要があります。
抽出範囲は前日分(0:00〜23:59)となります。前日分なので、cron回すときは日付が変わってからにしてください。
Twitterの認証はBasicです。oAuthは面倒です。
メール送信はmb_send_mailを素で使っているので、mailコマンドでメール送信できる環境が必要かも。
メールの書式はLoudTwitterに似せてありますが、各発言へのリンクは張っていませんのであしからず。
未確認事項として、エンコーディングUTF-8を指定していますが、これは環境依存かもしれません。文字化けするようならEUC-JPやShift_JISなんかも試してみて下さい。でも半角カナは化けます。
PHPだけど、PHPcliから実行することを想定しています。アカウント情報も埋め込みなので、Webから使うのはやめた方がいいと思います。

環境

私は自前のUbuntu鯖で動かしました。

導入

My Twitter

まずは、My Twitterというphpクラスを入手する。
これは、TwitterAPIをラップしたもの。
http://www.phpclasses.org/browse/package/4075.html
ただし、このスクリプトはPOSTメソッドで取得しようとするので、このままでは動きません。
myTimeLineParse関数内の、CURLOPT_POST指定部分をコメントアウトします。

//              curl_setopt($ch, CURLOPT_POST, true);
cUrl

このスクリプトcURLを使うので、「php5-curl」パッケージをインストール。

cli

cronで回すので、cliインタプリタ用パッケージ「php5-cli」をインストール。

今回のスクリプト

で、今回作ったスクリプトはこれ。

<?php
$username = 'xxxxxxxx';
$password = 'xxxxxxxx';
$send_to = "xxxxxxxx@d.hatena.ne.jp";
$from = "xxxxxxxx@xxxxx.xx.jp";

require_once('./my_twitter.php');
$twitter = new MyTwitter($username, $password);
$archive = $twitter->userTimeline(200);
$tcount = count($archive);
if ($tcount > 0)
{
        $body = '';
        $today = mktime(0, 0, 0, date('m'), date('d'), date('Y'));
        $yesterday = $today - 86400;
        for ($i = 0; $i < $tcount; $i++)
        {
                $tm = strtotime($archive[$i]['created_at']);
                if ($tm >= $yesterday and $tm < $today)
                {
                        $sts = date('H:i ', $tm) . $archive[$i]['text'] . "\n";
                        $body = $body . $sts;
                }
        }
        mb_language("japanese");
        mb_internal_encoding("UTF-8");
        $subj = date('Y/m/d分', $yesterday);
        mb_send_mail($send_to, $subj, $body, "From:".$from);
}
?>

protectedじゃない人の発言取るときは認証要らないんだけど、面倒なのでそのまま。
冒頭の4行を書き換えれば使えると思います。(通常Fromヘッダは不要ですね。)
あと、my_twitter.phpのインポート先は、php.iniでパスを通してあるところ(例:/usr/share/php:/usr/share/pear)に配置するか、フルパスで指定するかしてあげればよいかと。cronから実行するときは相対パスだとうまくいかないみたい。


あとは、my_twitter.phpと上記スクリプトを適当なフォルダに配置して、cronで回します。

TenageM:オフラインに焦点を当てたWM用Twitter投稿ツール。

要:.Net Compact Framework 2.0
Willcom03(WindowsMobile6.1 Classic)で動作確認。他環境でも多分行ける。根拠はない。

どんな人が使うの?

  • パケットは従量制が基本
  • 通信するなら無線か有線
  • いつも接続を「既定のインターネット設定」にして、勝手にダイヤルアップしないようにしている

そんな人。つまり俺。

タイムラインの取得は?

ありません。割り切り大事。目指せ単機能ツール。

使い道ないんじゃない?

そうですね。
とは言っても、定額で使いまくりの人だって使えます。
接続を「センタ名称設定」にしておいて、なんらかの手段で事前にダイヤルアップ接続を確立している必要はありますが。
接続が確立されてない場合は、アプリで発言を保存しておきますので、あとでまとめて投稿できます。
電波の届きにくいところなんかで使えるのではないでしょうか。
でも、そういう使い方は検証してません。なので、アプリで「オフラインモード」とかは持ってません。それなりに判定します。

機能

  • 投稿時オン/オフライン判定
  • 発言保存機能。以下の場合は保存します。
    • 投稿時にオフライン
    • 投稿失敗(ネットワークやサービスの問題)
    • 保存ボタン
  • 保存発言の1件削除、全件削除
  • 保存発言をまとめて投稿(20秒に1発言:近所迷惑対応)
  • コマンドライン対応(他アプリと連携。投稿即終了)


Today常駐は.netの機能だけでは難しそうだったのでやめました。

私の場合

Actionキー長押しに割り当てて、電車で思いついたことを保存したりしてます。

入手&導入

以下からどうぞ。
インストーラーとか作ってません。多分みんな使わないから。
使う場合は、事前に\Application Data(だっけ?)に「TenageM」というフォルダを手動で作ってください。手抜きですね。


http://tween.sourceforge.jp/TenageM.exe

ソース

ライセンスとか気にしない。お行儀悪くてすいません。
ソースはcodereposに置いてあります。
煮るなり焼くなり改変するなり流用するなり。リポジトリから捨てなければお好きにどうぞ。


http://coderepos.org/share/browser/lang/vb2005/TenageM

WindowsMobile用Twitter投稿単機能ツール0.0.0.1α

お試しで作ってみた。ただ単に投稿するだけ。UIもない。
とりあえず、MortScriptと組み合わせて使ってみようかと思う。
Today常駐できて、オフライン時は発言溜め込めるようにするのが最終目標。


動作も遅くて実用になるのか分からないので、今は公開しない。
ほしい人は教えてください。(もちろん自己責任)

js(wscript)製twitter投稿・取得ツール

ぷーる様が公開しているブログ「muumoo.jp」 http://muumoo.jp/ でjs製のtwitter投稿ツールが公開されています。手軽につぶやきたいときは、ランチャのbluewindから呼び出して使っていました。


で、jsで投稿できるんだから、取得もできそうだよね、と思って探したら、このブログでバージョンアップ版として公開されていました。


http://muumoo.jp/news/2008/06/24/0twitterclientjs.html


喜び勇んで試してみたのですが、最近のtwitter側仕様変更のため動きません。ならば、と修正と微妙な変更を加えましたので、ここで公開いたします。
とりあえず、twitterclient2.jsとでもしておきます。

(function() {
  var Twitter = function(id, pass){
    this.id = id;
    this.pass = pass;
    this.log = {};
  };
  Twitter.prototype.Update = function(message) {
    return this._get('http://twitter.com/statuses/update.json', message, 'POST');
  }
  Twitter.prototype.FriendTimeline = function() {
    return this._format(eval(this._get('http://twitter.com/statuses/friends_timeline.json', null, 'GET')));
  }
  Twitter.prototype.Mentions = function() {
    return this._format(eval(this._get('http://twitter.com/statuses/mentions.json', null, 'GET')));
  }
  Twitter.prototype._get = function(url, data, method) {
    var xmlhttp = new ActiveXObject('Msxml2.XMLHTTP');
    xmlhttp.open(method, url, false, this.id, this.pass);
    xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    xmlhttp.send(data);
    if(xmlhttp.status != 200) WScript.echo(xmlhttp.status + ' ' + xmlhttp.statusText);
    return xmlhttp.responseText;
  }
  Twitter.prototype._format = function(items) {
    if(items.length == 0) return '';
    var statuses = '';
    items.sort(function(a, b){ return a.id - b.id; });
    for(var i = 0; i < items.length; i++) {
      var item = items[i];
      if(this.log[item.id]) continue;
      
      var t = item.created_at.split(' ');
      var d = new Date(t[1] + ' ' + t[2] + ',' + t[5] + ' ' + t[3] + ' ' + t[4]);
      var line =
	  '●' +
          item.user.screen_name + ' [' +
          d.getFullYear() + '.' +
          (d.getMonth() + 1) + '.' +
          d.getDate() + ' ' +
          d.getHours() + ':' +
          d.getMinutes() + '] ' + '\n' +
          item.text + '\n';
      this.log[item.id] = 1;
      statuses += line;
    }
    return statuses;
  }
    
  
  var args = WScript.Arguments;
  if(args.length < 2) return;
  
  var twitter = new Twitter(args.Item(0), args.Item(1));
  if(args.length == 2) {
    var statuses = twitter.FriendTimeline();
    if(statuses.length > 0) WScript.echo(statuses);
  } else if(args.length == 3 && args.Item(2) == '@') {
    while(true) {
        var statuses = twitter.Mentions();
        if(statuses.length > 0) WScript.echo(statuses);
	WScript.Sleep(60 * 1000 * 10); // interval 10min
    }
  } else {
    var statuses = [];
    for(var i = 2; i < args.length; i++) {
      statuses.push(args.Item(i));
    }
    twitter.Update('status=' + encodeURIComponent(statuses.join(' ')));
  }
})();

使い方

オリジナルとほぼ変わりません。

  • WScriptで実行すると、結果がダイアログで表示されます。

wscript twitterclient2.js ユーザー名 パスワード

cscript twitterclient2.js ユーザー名 パスワード

オリジナルとの変更点

  • タイムライン取得は一度きりで(常駐せずに)結果を表示して終了します。引数はユーザー名とパスワードです。
  • 返信取得は常駐します。10分ごとにチェックします。引数はユーザー名とパスワードと@です。

(例:wscript twitterclient2.js ユーザー名 パスワード @)

  • 発言も一度きりで常駐しません。引数はユーザー名とパスワードと投稿内容です。間違って@のみの投稿をしてしまうと、裏で返信取得として常駐しちゃうのでお気をつけください。
  • 表示フォーマットを微調整

注意

タイムライン取得の場合、常駐しないため、cscriptで実行すると結果が一瞬で閉じてしまって見えません(汗
コマンドプロンプトから実行すれば見えるのですが、基本的にはWScriptからの実行を想定しています。(仕事中のチラミとかを想定)


返信取得は常駐するので、どちらで実行しても問題ありません。(不意の@を教えてほしいので、常駐します。)


あと、取得に関しては大なり小なりは文字化けします。
固定で置換すればよさそうですが、サボってます。


常駐した場合の終了方法ですが、cscriptならCtrl-cで。wscriptの場合は、タスクマネージャからwscript.exeを終了させてください。

Tween

Tween is the client program of twitter.

Software requirements

Overview

Not use twitter API, but get the html(/home,/replies,/directmessage) from twitter web page and scrape it.
State is beta, so if you have any problems or requests, please contact to @kiri_feather freely.

Operation manual(Japanese only)

Please visit Manual Site. (Author @syo68k)

(Thanks a lot!)

Screen shot


Additional icons for Tween(Japanese only)

The icons using in Tween are created by Minami.(Thanks a lot!)

You can replace the icons in Tween. Make a folder in the binary placed folder, and rename 'icons', then put some icons in the folder.

You can get extra icons here.
http://sourceforge.jp/projects/tween/wiki/%E3%82%A2%E3%82%A4%E3%82%B3%E3%83%B3%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%AE%E9%85%8D%E5%B8%83

TwitterとのHTTP通信内容

HTTPヘッダについて
keep-alive,connectionは変更する可能性あり。

<サインイン>
URL:http://twitter.com/sessions
ヘッダ:
	POST /sessions HTTP/1.1
	HOST: twitter.com
	User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9) Gecko/2008051206 Firefox/3.0		適当でもOK
	Accept-Encoding: gzip,deflate
	Connection: close
	Cookie: 初回は空。以後はTwitter関連接続で保持しているクッキー
	Content-Type: application/x-www-form-urlencoded
	Content-Length: データサイズ
データ:username_or_email=ユーザーID&password=パスワード

HTTP応答 302

<Recent取得>
URL:http://twitter.com/home
クエリ:
	1ページ目  =なし
	2ページ目以降=?page=n
ヘッダ:
	GET /home HTTP/1.1
	HOST: twitter.com
	User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9) Gecko/2008051206 Firefox/3.0
	Accept-Encoding: gzip,deflate
	Connection: close
	Cookie: Twitter関連接続で保持しているクッキー
	Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
	Accept-Language: ja,en-us;q=0.7,en;q=0.3
	Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7

HTTP応答:200

<Replies取得>
※Recent取得との違いは、URLのみ
URL:http://twitter.com/replies
クエリ:
	1ページ目  =なし
	2ページ目以降=?page=n
ヘッダ:
	GET /replies HTTP/1.1
	HOST: twitter.com
	User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9) Gecko/2008051206 Firefox/3.0
	Accept-Encoding: gzip,deflate
	Connection: close
	Cookie: Twitter関連接続で保持しているクッキー
	Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
	Accept-Language: ja,en-us;q=0.7,en;q=0.3
	Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7

HTTP応答:200

<受信DirectMessage取得>
※Recent取得との違いは、URLと1ページ目もクエリを付けていること。(なくても可)
URL:http://twitter.com/direct_messages
クエリ:?page=n
ヘッダ:
	GET /direct_messages HTTP/1.1
	HOST: twitter.com
	User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9) Gecko/2008051206 Firefox/3.0
	Accept-Encoding: gzip,deflate
	Connection: close
	Cookie: Twitter関連接続で保持しているクッキー
	Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
	Accept-Language: ja,en-us;q=0.7,en;q=0.3
	Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7

HTTP応答:200

<送信DirectMessage取得>
※Recent取得との違いは、URLと1ページ目もクエリを付けていること。(なくても可)
URL:http://twitter.com/direct_messages/sent
クエリ:?page=n
ヘッダ:
	GET /direct_messages/sent HTTP/1.1
	HOST: twitter.com
	User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9) Gecko/2008051206 Firefox/3.0
	Accept-Encoding: gzip,deflate
	Connection: close
	Cookie: Twitter関連接続で保持しているクッキー
	Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
	Accept-Language: ja,en-us;q=0.7,en;q=0.3
	Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7

HTTP応答:200

<投稿(Web)>
※通常、@、DMで差異なし
URL:http://twitter.com/status/update
クエリ:?page=1&tab=home
ヘッダ:
	POST /status/update HTTP/1.1
	HOST: twitter.com
	User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9) Gecko/2008051206 Firefox/3.0
	Accept-Encoding: gzip,deflate
	Connection: close
	Cookie: Twitter関連接続で保持しているクッキー
	Content-Type: application/x-www-form-urlencoded; charset=UTF-8
	Accept: text/javascript, text/html, application/xml, text/xml, */*
	x-prototype-version: 1.6.0.1
	x-requested-with: XMLHttpRequest
	Accept-Language: ja,en-us;q=0.7,en;q=0.3
	Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7
	Content-Length: データサイズ
データ:authenticity_token=認証トークン&authenticity_token=認証トークン&status=発言内容

HTTP応答 200

<投稿(API)>
※通常、@、DMで差異なし
URL:http://twitter.com/statuses/update.xml
クエリ:?page=1&tab=home
ヘッダ:
	POST /statuses/update.xml HTTP/1.1
	HOST: twitter.com
	User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9) Gecko/2008051206 Firefox/3.0
	Connection: close
	Content-Type: application/x-www-form-urlencoded
	Accept: text/html, */*
	X-Twitter-Client: Tween
	X-Twitter-Client-Version: 0.0.8.0
	X-Twitter-Client-URL: http://www.asahi-net.or.jp/~ne5h-ykmz/tween.xml
	Authorization: Basic ユーザー名:パスワードのBASE64エンコード
	Content-Length: データサイズ
データ:status=発言内容&source=Tween

HTTP応答 200

<発言削除(DM除く)>
URL:http://twitter.com/status/destroy/発言ID
ヘッダ:
	POST /status/destroy/発言ID HTTP/1.1
	HOST: twitter.com
	User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9) Gecko/2008051206 Firefox/3.0
	Accept-Encoding: gzip,deflate
	Connection: close
	Cookie: Twitter関連接続で保持しているクッキー
	Content-Type: application/x-www-form-urlencoded
	Accept: text/xml,application/xml,application/xhtml+xml,text/html,text/plain,image/png,*/*
	Referer: http://twitter.com/home
	Content-Length: データサイズ
データ:authenticity_token=認証トークン

HTTP応答 200

<DirectMessage削除>
URL:http://twitter.com/direct_messages/destroy/発言ID
ヘッダ:
	GET /direct_messages/destroy/発言ID HTTP/1.1
	HOST: twitter.com
	User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9) Gecko/2008051206 Firefox/3.0
	Accept-Encoding: gzip,deflate
	Connection: close
	Cookie: Twitter関連接続で保持しているクッキー
	Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
	Accept-Language: ja,en-us;q=0.7,en;q=0.3
	Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7

HTTP応答:200

<Fav追加>
URL:http://twitter.com/favourings/create/発言ID
ヘッダ:
	POST /favourings/create/発言ID HTTP/1.1
	HOST: twitter.com
	User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9) Gecko/2008051206 Firefox/3.0
	Accept-Encoding: gzip,deflate
	Connection: close
	Cookie: Twitter関連接続で保持しているクッキー
	Content-Type: application/x-www-form-urlencoded; charset=UTF-8
	Accept: text/javascript, text/html, application/xml, text/xml, */*
	x-prototype-version: 1.6.0.1
	x-requested-with: XMLHttpRequest
	Accept-Language: ja,en-us;q=0.7,en;q=0.3
	Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7
	Content-Length: データサイズ
データ:authenticity_token=認証トークン

HTTP応答 200

<Fav削除>
URL:http://twitter.com/favourings/destroy/発言ID
ヘッダ:
	POST /favourings/destroy/発言ID HTTP/1.1
	HOST: twitter.com
	User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ja; rv:1.9) Gecko/2008051206 Firefox/3.0
	Accept-Encoding: gzip,deflate
	Connection: close
	Cookie: Twitter関連接続で保持しているクッキー
	Content-Type: application/x-www-form-urlencoded; charset=UTF-8
	Accept: text/javascript, text/html, application/xml, text/xml, */*
	x-prototype-version: 1.6.0.1
	x-requested-with: XMLHttpRequest
	Accept-Language: ja,en-us;q=0.7,en;q=0.3
	Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7
	Content-Length: データサイズ
データ:authenticity_token=認証トークン

HTTP応答 200