birdきょうのつぶやき

きょうのつぶやき

府中運転免許試験場の国際免許コーナーが、今日は結構賑わっていた。夏休み海外へ行かれるおとーさん、って感じかな?僕は仕事だけど…(汗。 (11:32 twiccaから)

ひどい話だ…。 RT @hibikiw: みてる: asahi.com(朝日新聞社):一体誰が…ごみ焼却炉に大量の水銀 都内4施設が停止 - 社会 http://bit.ly/bTqq2w (11:37 twiccaから)

旧佐藤智仁くんは今年の3月からまた佐藤祐基くんに戻ってたんだ。知らなかった…。 (12:24 twiccaから)

RSSを提供しないBLOG、ってのはどういう意図があるのだろう…?利用者的には単純に不便=足が遠のくだけだと思うのだけれど。プロモーション目的なら逆効果なような。 (13:15 webから)

birdきょうのつぶやき

きょうのつぶやき

洗車したいのだがスコールが来そうで躊躇ちゅうなう… (14:59 webから)

2乗、と言うべきだったね<小学生には RT @matsutake: “小学生A「どっちが大きい数字言えるか勝負しようぜ!俺お前の言う数字の2倍ww」小学生B「じゃあ俺−1ね」” http://tumblr.com/xtcem28xg (19:45 twiccaから)

…と思ったら有葉に「じゃ1/2!」と返されました。参りました。 RT @digitune: 2乗、と言うべきだったね<小学生には RT @matsutake: “小学生A「どっちが大きい数字言えるか勝負しようぜ!俺お前の言う数字の2倍ww」小学生B「じゃあ俺−1ね」 (19:53 twiccaから)

ひびきさん @hibikiw のつぶやきより。それにしてもこのムービー見てもどんなアニメなのか全く分からないw>KURAU – 【MAD】 KURAU 新居昭乃 懐かしい宇宙 高画質版 【Full size】 http://youtu.be/Hm0IF-pa7W0 (20:01 webから)

そしてゼーガペインOP「キミヘ ムカウ ヒカリ」ED「リトルグッバイ」を。ゼーガペインは良いアニメだったにゃー。祝BD化!<遅いw。紹介してくれたSAK氏に感謝。 (20:14 webから)

大高さんや筧さんといった第三舞台の俳優さんを見ると、今でも無性にフジテレビの昔の深夜番組、「IQエンジン」が見たくなる。またどこかで見られるようにしてくれないかなぁ…。 (21:56 twiccaから)

そういや、今日は久しぶりに子供達とリトルビックプラネットをしました。鳥乃は未だにみんなでするLBPが一番好きみたい。今日も皆でお腹を抱えて笑い転げました。#lbp (22:26 twiccaから)

birdきょうのつぶやき

きょうのつぶやき

雨やまないね…。 (01:27 twiccaから)

雨降りだと思って雨の日用の靴で来たのに降ってない…。これですごい暑くなったらやだなぁ。 (09:49 twiccaから)

今サンデーで連載の「ARAGO」は、面白いのに掲載順を見るとあんまり人気がないみたいだ。面白いのに…<いつもの光景 (21:49 twiccaから)

なぜか連載(改行)になってしまったけど、もちろん連載中、の誤変換です。 (21:51 twiccaから)

birdきょうのつぶやき

きょうのつぶやき

今朝から(=洗浄剤の切れたタイミングで)、シェーバーをbraun prosonicから松下のlamdashへスイッチ。それまでずっと松下を使っていたのだけれど、前回更新時に一度は使ってみないと…と思いbraunにしてみました。が、僕にはやっぱりパナの方が向いているみたい。 (09:14 twiccaから)

理由はいくつかあるのだけれど、短い時間でさっぱり剃れる(ブラウンは時間がかかる)、ってのが一番大きな理由かなぁ。買ったときからそうだったので、経年劣化によるものではないと思う。機械自体の高級感やアルコール洗浄なところなんかは良かったんですけどね>ブラウン。 (09:21 twiccaから)

しかし今のラムダッシュのヘッドはデカ過ぎですな…。 (09:23 twiccaから)

話変わって、僕は普段xperiaを使うとき左手で操作していて(ちなみに右利きです)、本体を小指で支えています。そのうちその小指にペンダコならぬxperiaダコが出来そう…。 (09:27 twiccaから)

そういやケータイ(電話)を右手で持つか左手で持つかには結構深い理由や違いがありそう。ちなみに僕が右利きなのに電話は左なのは、昔本屋でアルバイトしていた時電話しながらメモをとらなきゃいけなかった必然からです。おお、深い<え。 (09:32 twiccaから)

「WORKING!」で散々伊波ちゃん(c.v.藤田咲)の声を聞いてから(すんません再放送も見てます・汗)、初音ミクのアルバムを聴くとやっぱり同じ人だな〜って分かりますね。 (09:38 twiccaから)

毎年のワンフェスの記事を見てると、かつての浮世絵のごとくそのうち海外の人もこの芸術に気がついて買い付けに来るだろうな、と思ったり。しかしなんで村上隆氏だけ評価が突出してるのだろう?「工業製品」でなく「芸術品」と位置付けたのか彼だけだったから、とか? (09:56 twiccaから)

androidの天気予報widgetがずっと晴れだなーと思ったら、単に更新されてなかっただけだった…orz。 (11:34 twiccaから)

な、なんですと〜!! うぬぬぬぬ… RT @Uruma: 「びっくりマウス for iPad」は、作れなくなりました。SCEがダメだって。 (11:43 twiccaから)

余地なしって…(涙 RT @Uruma: まあ杓子定規に言えばそりゃそうなんだろうね。でも10年経ってるわけだし、もうプレステ2ないわけだし、ロイヤリティも払うつもりだったんだけど、余地なしでしたね。 (12:02 twiccaから)

「引用して返信」だとFBにフィードされないみたいなので再送信。 RT @digitune: な、なんですと〜!! うぬぬぬぬ… RT @Uruma: 「びっくりマウス for iPad」は、作れなくなりました。SCEがダメだって。 (12:13 twiccaから)

こっちも。 RT @digitune: 余地なしって…(涙 RT @Uruma: まあ杓子定規に言えばそりゃそうなんだろうね。でも10年経ってるわけだし、もうプレステ2ないわけだし、ロイヤリティも払うつもりだったんだけど、余地なしでしたね。 (12:14 twiccaから)

今日はdiva2の発売日っ!!…ということを電車で前に座ってるおにーさんがプレイしているのを見て思い出した(汗。残業してる場合じゃなかった。 (21:31 twiccaから)

windows7をちゃんと使うのって実は初めてなんだけど(とゆーかvistaすら使ったことない・汗)、「システムの詳細設定」から「パフォーマンス優先」を選んでみたら、懐かしのクラシックテーマになっちゃって驚いた。7でも生き残ってたんですね。クラシックな7はまるで2000みたいだ。 (21:39 twiccaから)

パフォーマンスの設定と個人設定:テーマ設定の関係のカオスっぷりに、久々にMS的な何かに触れた感じだ。welcome back to the chaotic world! (21:59 twiccaから)

ふむふむ、隣のおにーさんによると、diva1からの引き継ぎ曲も結構pv変わってるみたいだな<覗くのやめなさい。 (22:04 twiccaから)

今日久しぶりに傘使ったら、なんだかとってもカビ臭い…。ちゃんと干さないとダメだなぁ。 (22:12 twiccaから)

birdきょうのつぶやき

きょうのつぶやき

調布で終電ゲットだぜ! (00:24 twiccaから)

昨日の飲み会のメンバーのうち二人はiPhone4持ちだった。そんなわけでお約束の「どっちが先にアンテナなくせるか競争〜」wをやってもらったのだけれど、そもそも電波が強かったのかあんまり減らなかった。ざんねんじりゅうにのりおくれた。 (09:22 twiccaから)

「尖塔 萩原正次歌集」読了。祖父の二冊目の歌集です。活版が廃れ、オフセット印刷へ移り変わっていく留めようのない変化を、積極的に受け入れようとしながらも、クレーンで持ち上げられ引き取られていく古く大きな活版印刷機への思いを歌った歌など、とても良かった。 (21:01 twiccaから)

この歌集から、僕ら孫世代と同時代の歌もちらほら出てきます。八王子絹の道に関する歌は、当時祖父が歌を作っていたことを僕も覚えています。祖父の吟行(子供にとってはただの散歩)について歩くことは、とても楽しかった記憶があります。 (21:05 twiccaから)

こんな時間なのにセミがすごい鳴いてる。 (21:34 twiccaから)

birdきょうのつぶやき

きょうのつぶやき

人間の歩き方って 、近年では生体認証にも用いられ始めているほど、一人一人異なるもの。なので「けいおん!!」と「WORKING!」のエンディング対決は、「WORKING!」の圧倒的勝利なのだ。なお「けいおん!!」は今の(後半の)エンディングの方ね。 (00:18 twiccaから)

新しいけいおんのエンディング、凄くかっこいいんだけど、あの歩くシーンは違和感があった。そして「WORKING!」は、最近見たアニメの中では図抜けて動きが良かったと思う。 (00:22 twiccaから)

団地の修繕もようやく終わりが見えてきて、この週末、やっと網戸を戻せました。そんなわけで、今日は夕立がしっかり降ったこともあって、とても涼しい風が吹いていて、久々にぐっすり眠れそうです。 (00:39 twiccaから)

そういや、週末にiPadからも開発作業が出来ないかしら…とSSHクライアントを探したら、あんまり選択肢がなかった(´・ω・`)。仕方がないので1500円のiSSHを買ったけど、正直VNC機能は要らないなぁ。 (09:32 twiccaから)

やば、これすごく欲しいかも…。 http://bit.ly/bQCHim (09:45 twiccaから)

image 0おいしー。 http://twitpic.com/2957sd (22:24 twiccaから)

image 1スーパー今井さん。 http://twitpic.com/29581s (22:25 twiccaから)

birdきょうのつぶやき

きょうのつぶやき

そういえばDiva2って今週発売でしたよね(今調べたら29日らしい)。楽しみ〜。 (09:34 twiccaから)

同意。身内に印刷関係(非大手)がいるので他人事ではない。 RT @kapi_xx: 電子ブックやら音楽配信やらもそーだけど、既存の物理メディア業界が没落した後の失業問題ってのはもっと議論されても良かろう (09:57 twiccaから)

僕が大学時代バイトしてた本屋は、息子さんに代替わりしたタイミングでPC修理メインのお店に変わった。返品不可な岩波文庫だけまだ売ってる。 RT @kapi_xx: 例えば街の本屋は何になっていけばいいのか (10:00 twiccaから)

人材の流動性問題ってのは、制度的な面ももちろんそうだけど、意識的な面も日本の場合大きい気がするな。蛙の子は蛙的世襲の例がものすごく頻繁に目に入るからね。それがフツー、くらいならともかく、そっちのが良い、と考えてる人も多そう。 (10:08 twiccaから)

だからこそ、多少無理矢理にでも制度面から流動化を促すべきなのかもしれないけど。 (10:11 twiccaから)

先々週末に子供達とプールに行ったとき焼けた背中の皮がむけだした…。毎年のことではありますが、しばらくお見苦しい点にはご容赦を。 (13:10 twiccaから)

アドエスの調子がいよいよおかしい。知らぬ間に電源が落ちていることもしばしば。早くWMじゃないスマートフォン出してくれないかなー。それとももはや期待するだけ無駄なのか。 (13:21 twiccaから)

そういや、必ずしもテッキーじゃない人が、iPhoneと比較して「androidはクソ」と言うとき、主にどの辺りについて批判しているのか興味あるな。まさかuiのフレームレートではあるまい。 (13:28 twiccaから)

ちょっと興味あるー。けどしょっぱいのかな? RT @hibikiw: RT @tokyo_ayano: 久しぶりにトウモロコシ食べたくなったw : “今まではなんだったんだ…と思うくらいおいしくトウモロコシをゆでる方法 http://bit.ly/bk4Dbp (15:21 twiccaから)

おお、貴重な情報ありがとう。試してみるよ。 RT @kapi_xx: @digitune バッテリーの接点だな。接点復活剤を使うべし (15:24 twiccaから)

おお、やはりフレームレートじうよう。あと、それを言っちゃあおしまいかと>センスがダサい RT @kapi_xx: @digitune 嫁はスクロールがガクガクするからヤダっつってたぞ。俺は気にしないけど。一言で言えば作りのセンスがダサいんだろ (15:27 twiccaから)

萩原正次「歌集・変声期」読了。萩原正次とは、僕の祖父です。先週末僕・あゆみさんそれぞれの身内イベントで実家へ戻った際、ふと思い立って借りてきました。戦中の朝鮮・中国への遠征から、昭和35年頃の、祖父がちょうど今の僕と同じか少し上くらいの年代にかけての歌が収録されています。 (22:08 webから)

特に、日々の何気ないワンシーンを切り取ったような歌がとても良かった。戦中戦後の街の様子から、子供たち(祖父の子なので、つまり僕の親のことなのですが)が病気したり遊んだり叱られたり、印刷屋という小自営業を営む大変さなどが伝わってきて、じーんとしました。 (22:16 webから)

そんなことを思いながら読み終わってみたら、あとがきで祖父自身が、「戦中戦後の生活記録と云うか育児記録と云うようなものでどれも捨てるのが惜しい、一首読むことによってその時々の情景が鮮明に浮んで来る、これは作歌したものの特権のような幸せ」と、同じようなことを書いていておかしかった。 (22:21 webから)

ちなみに祖父はさっき書いたとおり印刷屋でしたので、自分の歌集を自分で印刷して本にしていました。装丁は画家で美術の教師でもある、僕の叔母が担当して。うちの親は「職権濫用」と言って笑っていました。 (22:25 webから)

birdTwitterでの自分のTweetsをtDiaryにまとめて投稿する - その1. 過去ログ編, Twitterでの自分のTweetsをtDiaryにまとめて投稿する - その2. 日次バッチ編, きょうのつぶやき

Twitterでの自分のTweetsをtDiaryにまとめて投稿する - その1. 過去ログ編

久々にこのブログを見た人は、左側の「最近の話題」を見てびっくりしてしまったかもしれませんが、この週末はいろいろ忙しい中、Twitterに溜まっていた自分の過去のつぶやき(Tweets)を、この自分のブログ(tDiary)に毎日まとめて投稿するスクリプトを作成したりしていました。忙しいとかえってそういうことをしたくなったりしますよね(笑。

どうしてそんなことしたくなったのか、というといくつか理由があって、1)Twitterを使うようになってブログの更新頻度が激減してしまっているのを何とかしたいのが第一(笑、2)一つの会社に管理されているTwitter内の自分の書き込みのバックアップを念のため取っておきたかった1、3)さらにTwitterに投稿している写真データ2もバックアップしておきたい、4)Twitterは利用しないがこっちは見ている人もいるかもしれない、などなどでした。Twitterを単なる利用者としてではなく、開発者として叩いてみておきたかった、という面もあります。

さて、Twitterでの自分のつぶやきをtDiaryへ登録する、という今回僕がやりたかったことと同じことをやっている人は、ググッてみると結構たくさんいらっしゃいます。しかし、僕がググった限り、僕のニーズにピッタリ合った方法は見つかりませんでした。主に問題だったのが、TwitPicに登録された写真の扱いで、写真へのTwitPicサイトへのリンクを作成したりしている人もたくさんいらっしゃったのですが、投稿された写真そのものをローカルにダウンロードしてバックアップしておく、という方法を取っている人は見つかりませんでした。また、同じようなことをしていても一部の処理を手動で行っていたり(僕はcron起動で毎日勝手に投稿してくれるような形にしたいと思っていました)、投稿されるTweetsのフォーマット・中身がイマイチだったり、そもそも投稿スクリプトが公開されていなかったりと、どうもぴったり来るものはなさそうだということがわかりました。

既存のソリューションをググッて探す一方で、自分でTwitter/TwitPicからつぶやきが写真を取り出して投稿するのがどのくらい難しいのかも調べ始めていたんですが、アクセスのための材料(ドキュメント・ライブラリ)も既に豊富にそろっており、そんなに難しくなさそうなことが伺えました。そんなわけで自分で作ってみることにしてしまったわけです。

一口に「自分のTweetsをまとめてtDiaryに再投稿する」といっても、この問題には大きく2つの側面があります。一つが既に1400tweetsあまりたまった自分の過去のつぶやきをどうするか、もう一つが今後毎日まとめ投稿をするための仕組み作りです。もちろん、両者に共通する技術要素は多いですが、異なる部分も多いと思いました。例えば前者(過去ログ)の問題は、ワンショットの処理となりますからテキトーなスクリプト+ある程度のマニュアル処理でも問題ありません。また今この瞬間に動きさえすれば良いので、最近話題の「Twitterの認証問題3」も関係ありません。そんなわけで、まずは前者の問題に取り組むことにしました。基本的な方針としては、後者の問題向けの知識を蓄えること+とにかく手間をかけないこと、としました。また、上でも書きましたが、Twitterに投稿されている自分のつぶやきをこのtDiary側へコピーすること、個人宛つぶやき(@〜で始まるつぶやき)は含めないこと、自分のTwitPicへ投稿した写真はローカルにダウンロードしたのち、tDiaryのimage_exプラグインを使って表示すること、あたりを最低限の要求仕様とすることにしました。

さてまず、前者後者共通してサーバ側での処理のために使うツールとしては、今回はrubyを選択することにしました。個人的にはまだperlやshほどrubyのコードは書いたことはなく、少し不安な(というかめんどくさい)面もあったんですが、特にネット系のツールをお手軽に書くための材料が豊富に揃っていること、個人的にそろそろ(というか遅過ぎるけど・汗)rubyにも慣れておきたいと思ったという辺りが主な理由です。結果的にはrubyの選択は大正解でしたね。とにかく何をやるにも楽で、短い時間でささっとコードを書かないといけない今回の僕のようなケースにはピッタリでした。

Twitterにはいろいろ公開されているAPIがありますが、その中で今回僕が使ったのは、id指定(スクリーンネーム指定)でつぶやきを時系列順で取得する、user_timeline APIだけです。まず最初に、自分のプログラムのデバッグでTwitter側に負荷をかけるのも忍びなかったため、とりあえず過去の自分のつぶやきを全て、JSON形式でダウンロードしておくことにしました。ワンショットでダウンロード出来ればよかったので、今回はwgetコマンドとrubyを使い、以下のようにして行ないました。

  • まず、wgetコマンドで最初(新しい方から)200件のつぶやきをJSON形式でダウンロードします。この時、既にTwitterへログイン済みの(cookieのついた)ブラウザならそのまま実行できますが、wgetのようなcookieを持たないクライアントを使う場合、BASIC認証を指定する必要があります。

    $ wget –user=SCREEN_NAME –password=PASSWORD -O 1.json http://api.twitter.com/1/statuses/user_timeline/SCREEN_NAME.json?count=200

  • 次にダウンロードされたJSONファイルを例えば下記のようなスクリプトを使ってrubyで読み、最後の要素が含む"id"値を調べます4

#!/usr/bin/env ruby  
require 'rubygems'  
require 'json/pure'  
  
json_doc = ""  
open("#{1.json", "r") do |file|  
  json_doc = file.read  
end  
JSON.parse(json_doc).each do |status|  
  puts "id = #{status['id']}"  
end  
  • さらに、上で調べた最後の要素(=一番古い要素)のidを使って、以下のように「それよりも古いつぶやき」を再びJSON形式でダウンロードします。

    $ wget –user=SCREEN_NAME –password=PASSWORD -O 2.json “http://api.twitter.com/1/statuses/user_timeline/SCREEN_NAME.json?count=200&max_id=[上で調べた一番古いつぶやきのid]”

  • 以上を、古いつぶやきがなくなるまで繰り返します。

ちなみに上記処理はとても単純な処理なので、上の処理自体を一つのrubyスクリプトにすることも簡単なわけですが、僕が試していたところ、上記のようなAPI呼出を間髪入れず実行してしまうと、時々TwitterがJSON形式のデータではなく何だか分からないHTMLデータを返すことがあり(もしかしたら鯨が出てたのかなぁ?)、今回はたかだか8回程度の繰り返しだったのでマニュアルで処理してしまいました。

さて、そうやって手元にJSON形式の過去つぶやきデータがダウンロードされたあとは、tDiaryへそれらを適当に整形してPOSTするだけです。最初、tDiaryへHTTP POSTでつぶやきを投稿するのではなく、直接ローカルにある日記データに追記してしまおうかとも考えたのですが、キャッシュやRSSを生成しているプラグインなどへの影響を考えて、またしてもwgetコマンドを使ってHTTP POSTする、という選択を取ることにしました5

過去ログPOSTに使ったスクリプトは下記の通りです。自分にとってスクラッチから書いた初めてのrubyスクリプト&ワンショットしか動かさないつもりだったので超テキトーな点はご容赦くだされ。

#!/usr/bin/env ruby  
  
require 'rubygems'  
require 'json/pure'  
require 'parsedate'  
require 'kconv'  
require 'cgi'  
require 'uri'  
  
SCREEN_NAME = 'SCREEN_NAME'  
TDIARY_UPDATE_URI = 'http://memo.digitune.org/update.rb'  
TWITTER_URI = 'http://twitter.com/'  
TWITPIC_URI = 'http://twitpic.com/'  
IMAGE_PATH = '/home/kazawa/src/tdiary/images/'  
all_tweets = {}  
$image_seq = 0  
  
(1..8).each do |i|  
  json_doc = ""  
  open("#{i}.json", "r") do |file|  
    json_doc = file.read  
  end  
  JSON.parse(json_doc).each do |status|  
    all_tweets[status['id']] = status  
  end  
end  
  
def link_uri(tweet)
  URI.extract(tweet, ["http", "https"]) do |uri|  
    tweet = tweet.gsub(uri, "<a href=\"#{uri}\">#{uri}</a>")
  end  
  tweet  
end  
  
def link_twitter(tweet)
  tweet = tweet.gsub(/@(\w+)/, "@<a href=\"#{TWITTER_URI}\\1\">\\1</a>")
  tweet  
end  
  
def download_twitpic(tweet, date)
  URI.extract(tweet) do |uri|  
    if /^#{TWITPIC_URI}/ =~ uri  
      res = `wget -O - #{uri} 2>/dev/null`  
      own_photo = nil  
      res.each_line do |line|  
        if /photo_username.*\">(\w+)<\// =~ line  
          puts "photo_username = #{$1.strip}"  
          own_photo = 1 if $1.strip == SCREEN_NAME  
        end  
      end  
      break if ! own_photo  
      url = ""  
      res = `wget -O - #{uri}/full 2>/dev/null`  
      res.each_line do |line|  
        if /img.*src=\"([^\"]+)\".*alt/ =~ line  
          url = $1  
          puts "url = #{url}"  
        end  
      end  
      puts "wget -O #{IMAGE_PATH}#{date}_#{$image_seq}.jpg --referer=#{uri}/full \"#{url}\""  
      system "wget -O #{IMAGE_PATH}#{date}_#{$image_seq}.jpg --referer=#{uri}/full \"#{url}\""  
      puts "convert #{IMAGE_PATH}#{date}_#{$image_seq}.jpg -resize 60x80 #{IMAGE_PATH}s#{date}_#{$image_seq}.jpg"  
      system "convert #{IMAGE_PATH}#{date}_#{$image_seq}.jpg -resize 60x80 #{IMAGE_PATH}s#{date}_#{$image_seq}.jpg"  
      tweet = "<%=image_right #{$image_seq}%>" + tweet  
      $image_seq += 1  
    end  
  end  
  tweet  
end  
  
def post_tweets(body, last_t)
  body = "きょうのつぶやき\n" + body  
  puts "body => #{body}"  
  post_data = "old=#{last_t.strftime('%Y%m%d')}&year=#{last_t.year}&month=#{last_t.month}&day=#{last_t.day}&title=&body=#{CGI.escape(body.toeuc)}&makerss_update=false&append=#{CGI.escape(' 追記 '.toeuc)}"  
  puts "wget -d --user TDIARY_USER --password TDIARY_PASS --referer #{TDIARY_UPDATE_URI} --post-data '#{post_data}' #{TDIARY_UPDATE_URI}"  
  system "wget -d --user TDIARY_USER --password TDIARY_PASS --referer #{TDIARY_UPDATE_URI} --post-data '#{post_data}' #{TDIARY_UPDATE_URI}"  
end  
  
body = ""  
last_t = nil  
last_date = nil  
all_tweets.keys.sort.each do |id|  
  status = all_tweets[id]  
  d = ParseDate::parsedate(status['created_at'])
  t = Time.gm(*d[0..5]).localtime  
  ts = t.strftime("%F")
  if last_date != nil && last_date != ts  
    post_tweets(body, last_t) if body != ""  
    $image_seq = 0  
    body = ""  
  end  
  if /^@/ =~ status['text']  
    puts ("skip: #{status['text']}")
    next  
  end  
  tweet = download_twitpic(status['text'], t.strftime('%Y%m%d'))
  tweet = link_twitter(link_uri(tweet))
  body = body + "<p>#{tweet} <font size=-2>(#{t.strftime('%H:%M')} #{status['source']}から)</font></p>\n"  
  last_t = t  
  last_date = ts  
end  
post_tweets(body, last_t) if body != ""  

随所に乱れ飛ぶputsはデバッグ表示ですので鬱陶しければ消しても大丈夫です。上記スクリプトはまるでrubyっぽくなかったり(汗、TwitPicのHTMLを超適当に読み込んでいたり、Twitterにハッシュタグに未対応だったり、サムネイルイメージのサイズが元画像にかかわらず固定だったりといろいろショボい箇所があるんですが、まぁとりあえず動いたのでこれはこれで良いのでは、と<ヲ。さて、その2. 日次バッチ編へ続きます。

Twitterでの自分のTweetsをtDiaryにまとめて投稿する - その2. 日次バッチ編

さて、過去ログの処理が終わったので、次は今後のための日次バッチの作成です。やるべきことは過去ログ編とほとんど変わらないため、スクリプトももうほとんどできている、といっても過言ではないのですが、上で書いたとおり、一点新しいつぶやきをJSON形式で取得するための、Twitter APIの認証部分については、上でやったようなテキトーなことではすぐに動かなくなってしまいますので6、もう少し真面目に考える必要がありました。

しかしまぁ最近は良い時代になったもので、そのような技術的課題に直面しても、ことオープンな世界の出来事であれば、ほぼ確実に先達が解決済みだったりします。今回のケースもグーグル先生にちょっと聞いてみさえすればすぐに、ruby+OAuthを実現しておられる方のページが見つかりました。僕が今回主に参考にしたのはこちらのページです。どうもありがとうございました>しばそんさん。

そんなわけで上記ページをベースに元のスクリプトをOAuthに対応させ、またTwitterのハッシュタグに対応させたり多少コードを整理したりした結果の、日次バッチ用スクリプトを以下に貼っておきます。僕はこのスクリプトを夜中の0:00に実行されるよう、cronに設定しています。あ、実行前に、最後に投稿した過去つぶやきのidを、last_id.txtファイルに書いておかないと上手く動きません。いろいろテキトー過ぎるスクリプトで申し訳ないッス…。

#! /usr/bin/ruby  
# encoding: utf-8  
  
require 'time'  
require 'rubygems'  
require 'oauth'  
require 'rubytter'  
require 'kconv'  
require 'parsedate'  
require 'cgi'  
require 'uri'  
require 'fileutils'  
  
# constants  
SCREEN_NAME = 'SCREEN_NAME'  
TDIARY_UPDATE_URI = 'http://memo.digitune.org/update.rb'  
TWITTER_URI = 'http://twitter.com/'  
SEARCH_PATH = 'search?q='  
TWITPIC_URI = 'http://twitpic.com/'  
IMAGE_PATH = '/home/kazawa/src/tdiary/images/'  
LAST_ID_PATH = '/home/kazawa/src/tweets2tdiary/last_id.txt'  
TITLE = "きょうのつぶやき\n"  
  
# secret information  
CONSUMER_KEY = 'CONSUMER_KEY'  
CONSUMER_SECRET = 'CONSUMER_SECRET'  
ACCESS_TOKEN = 'ACCESS_TOKEN'  
ACCESS_TOKEN_SECRET = 'ACCESS_TOKEN_SECRET'  
  
# global variables  
$image_seq = 0  
  
# functions  
def link_uri(tweet)
  URI.extract(tweet, ["http", "https"]) do |uri|  
    tweet = tweet.gsub(uri, "<a href=\"#{uri}\">#{uri}</a>")
  end  
  tweet  
end  
  
def link_twitter(tweet)
  tweet = tweet.gsub(/@(\w+)/, "@<a href=\"#{TWITTER_URI}\\1\">\\1</a>")
  tweet = tweet.gsub(/#(\w+)/, "<a href=\"#{TWITTER_URI}#{SEARCH_PATH}%23\\1\">#\\1</a>")
  tweet  
end  
  
def download_twitpic(tweet, date)
  URI.extract(tweet) do |uri|  
    if /^#{TWITPIC_URI}/ =~ uri  
      res = `wget -O - #{uri} 2>/dev/null`  
      own_photo = nil  
      res.each_line do |line|  
        if /photo_username.*\">(\w+)<\// =~ line  
          puts "DEBUG:photo_username = #{$1.strip}"  
          own_photo = 1 if $1.strip == SCREEN_NAME  
        end  
      end  
      break if ! own_photo  
      url = ""  
      res = `wget -O - #{uri}/full 2>/dev/null`  
      res.each_line do |line|  
        if /img.*src=\"([^\"]+)\".*alt/ =~ line  
          url = $1  
          puts "DEBUG:url = #{url}"  
        end  
      end  
      puts "DEBUG:wget -O #{IMAGE_PATH}#{date}_#{$image_seq}.jpg --referer=#{uri}/full \"#{url}\" 2>/dev/null"  
      system "wget -O #{IMAGE_PATH}#{date}_#{$image_seq}.jpg --referer=#{uri}/full \"#{url}\" 2>/dev/null"  
      puts "DEBUG:convert #{IMAGE_PATH}#{date}_#{$image_seq}.jpg -resize 60x80 #{IMAGE_PATH}s#{date}_#{$image_seq}.jpg"  
      system "convert #{IMAGE_PATH}#{date}_#{$image_seq}.jpg -resize 60x80 #{IMAGE_PATH}s#{date}_#{$image_seq}.jpg"  
      tweet = "<%=image_right #{$image_seq}%>" + tweet  
      $image_seq += 1  
    end  
  end  
  tweet  
end  
  
def post_tweets(body, last_t)
  body = TITLE + body  
  puts "DEBUG:body => #{body}"  
  post_data = "old=#{last_t.strftime('%Y%m%d')}&year=#{last_t.year}&month=#{last_t.month}&day=#{last_t.day}&title=&body=#{CGI.escape(body.toeuc)}&append=#{CGI.escape(' 追記 '.toeuc)}"  
  puts "DEBUG:wget -O /dev/null --user USERNAME --password PASSWORD --referer #{TDIARY_UPDATE_URI} --post-data '#{post_data}' #{TDIARY_UPDATE_URI} 2>/dev/null"  
  system "wget -O /dev/null --user USERNAME --password PASSWORD --referer #{TDIARY_UPDATE_URI} --post-data '#{post_data}' #{TDIARY_UPDATE_URI} 2>/dev/null"  
end  
  
# connect  
consumer = OAuth::Consumer.new(  
  CONSUMER_KEY,  
  CONSUMER_SECRET,  
  :site => 'http://twitter.com'  
)
  
access_token = OAuth::AccessToken.new(  
  consumer,  
  ACCESS_TOKEN,  
  ACCESS_TOKEN_SECRET  
)
  
client = OAuthRubytter.new(access_token)
  
# read last_id  
last_id = 0  
open(LAST_ID_PATH, "r") do |file|  
  last_id = file.gets.chomp.strip  
end  
puts "DEBUG:last_id = #{last_id}"  
  
# read tweets  
body = ""  
last_t = nil  
last_date = nil  
client.user_timeline('digitune', {:since_id => last_id, :count => 200}).reverse_each do |status|  
  puts "DEBUG:id = #{status.id}"  
  last_id = status.id  
  d = ParseDate::parsedate(status.created_at)
  t = Time.gm(*d[0..5]).localtime  
  ts = t.strftime("%F")
  if last_date != nil && last_date != ts  
    post_tweets(body, last_t) if body != ""  
    $image_seq = 0  
    body = ""  
  end  
  if /^@/ =~ status.text  
    puts "DEBUG:skip: #{status.text}"  
    next  
  end  
  tweet = download_twitpic(status.text, t.strftime('%Y%m%d'))
  tweet = link_twitter(link_uri(tweet))
  body = body + "<p>#{tweet} <font size=-2>(#{t.strftime('%H:%M')} #{status.source}から)</font></p>\n"  
  last_t = t  
  last_date = ts  
end  
post_tweets(body, last_t) if body != ""  
  
# write last_id  
FileUtils.cp(LAST_ID_PATH, LAST_ID_PATH + ".old")
open(LAST_ID_PATH, "w") do |file|  
  file.puts last_id  
end  

きょうのつぶやき

あーテステス #bot (19:20 webから)

TwitterのつぶやきをまとめてtDiaryに投稿するテキトーなスクリプトを書きました。あまりにテキトー過ぎでも驚かぬよう。>「Twitterでの自分のTweetsをtDiaryにまとめて投稿する」http://memo.digitune.org/?date=20100725 (22:29 webから)

image 0テストも兼ねて。鳥乃が作った我が家の愛犬、スー。 http://twitpic.com/28kc0o (22:39 twiccaから)

うおっと家庭内LANからお家サーバには素直には繋がらないんだった。えーとどうするんだっけ?(汗。androidに/etc/hostsってある? (23:18 twiccaから)

birdきょうのつぶやき

きょうのつぶやき

後者。AMPには承認プロセスがないので。 RT @m_masaru: 逆にandroid TVにDMM.TV for Androidが来ないのはgoogleがピンはねできなくなるから承認が降りないのか、DMM自身がBD-Jと比べて市場に価値がないと思っているのかどっちなんだろう。 (09:48 twiccaから)

birdきょうのつぶやき

きょうのつぶやき

武満徹の名曲、「〇と△の歌」を知らんのか。 RT @yukatan: RT @gamme: 今日の覚えとくべき「愛で勝った人は「愛は勝つ」なんて歌わない。地球は丸いなんてわざわざ歌わないじゃん」 (09:24 twiccaから)

まぁふつーは知らないわな(^_^;) (09:25 twiccaから)

発売前後の熱狂も冷めて、最近はdisられ気味なニュアンスで話題になることの多いiPadだけど、我が家ではごくフツーにリビングweb&youtube端末として活躍中。今欲しいのはまともなニコ動プレーヤーだなー。公式には期待できないのか…。 (09:35 twiccaから)

雨後の竹の子のように出ている電子書籍系アプリもそれなりには眺めてるけど、そもそも最近の僕の生活サイクルには「雑誌を読む」という時間が全くないのが最大の障壁。僕の中では雑誌はもう完全にwebに淘汰されてる。 (09:42 twiccaから)

そう考えると、雑誌的電子書籍メインのiPadより文庫的電子書籍メインのkindleの方が、こと電子書籍というコンテキストでは僕には向いてるのかもしれないな。 (09:48 twiccaから)

iPadもkindleも、最近街でも見かける機会が多くなってきました。面白いのは、kindleは男女同じくらいの割合で見かけるのに、iPadを外で使っているのは男性ばかり(サンプル数は両手分くらい)。やっぱりあの重量がネックなのかな。 (09:53 twiccaから)

今、外苑東通りをローダウンされたムラーノが通ってった…。い、意味分からん! (13:21 twiccaから)

First | Prev | 345 | 346 | 347 | 348 | 349 | Next | Last