2008年 10月、私は多くの人々と同じく、好奇心から Twitter アカウントを作り、このサービスをよく理解するために友だちをフォローし、適当な検索を思い付くまま行ってみました。140 文字で通信するというアイデアは人気を呼びそうにないという印象を得ましたが、私は思いがけない出来事によって Twitter の真の価値を理解するようになりました。
2009年 7月の初め、私が使っている Web ホスティング・プロバイダーのサービスが停止したときのことです。手当たり次第に Web を検索したところ、シアトルの Fisher Plaza で起こった火事が原因だと指摘する情報が見つかりました。従来の Web ベースのソースからの情報はリアルタイムではなく、いつサービスが復旧するのかを知る参考にもなりません。その一方、Twitter を検索してみると、この事故を話題にした個人アカウントが見つかりました。なかには、現場で何が起こっているかをリアルタイムで伝えている情報もあります。例えば、ホスティング・サービスが復旧する少し前に、あるツイートでは建物の外部にディーゼル発電機があることを伝えていました。
私はこの出来事をきっかけに、Twitter の真の威力は個人やグループの間でのオープンでリアルタイムの情報交換ができることであると実感したわけです。しかもそこには、ユーザーの行動に関する情報、そして地域レベルと世界レベルでの動向に関する情報が宝の山となって存在しています。この記事では、Ruby 言語と Twitetr の API ラッパーである Twitter gem を使用した単純なスクリプトを背景に、この情報の宝庫を実際に利用する方法を探ります。さらに、他の Web サービスおよびアプリケーションを使用してデータを視覚化する、単純なマッシュアップを作成する方法を紹介します。
初期の頃の Web が目的としていたのは人間とマシンとの対話でしたが、現在の Web が目的とするのは、Web サービスを使用して実現するマシン同士の対話です。このようなサービスは、さまざまな Google サービスから LinkedIn、Facebook、そして Twitter に至るまで、人気の高いほとんどの Web サイトを対象に存在しています。これらの Web サービスでは、外部アプリケーションから Web サイトのコンテンツに対してクエリーを実行したり、操作を行ったりするための API を作成しています。
Web サービスはさまざまなスタイルを使って実装されますが、現在最もよく使用されているスタイルは、REST (Representational State Transfer)
です。REST の実装の 1 つはお馴染みの HTTP プロトコル上に実装されており、(GET、PUT、POST、DELETE といった標準的な HTTP 操作を使用する) RESTful なアーキテクチャーの媒体として HTTP が存在することを可能にしています。Twitter の API は、この媒体の抽象化として開発されているため、Twitter には REST や、HTTP、あるいは XML や JSON などのデータ・フォーマットの情報はなく、代わりに Ruby 言語に巧みに統合されるオブジェクト・ベースのインターフェースがあるというわけです。
このセクションでは、Ruby で Twitter API を使用する方法を説明します。まずは、必要なリソースを入手しなければなりません。私と同じく Ubuntu
Linux を使用している場合には、apt フレームワークを使用することになります。
最新の完全な Ruby ディストリビューション (ダウンロード・サイズは約 13MB) を入手するには、以下の内容をコマンドラインで実行します。
$ sudo apt-get install ruby1.9.1-full |
次に、gem ユーティリティーを使って Twitter gem を取得します。
$ sudo gem install twitter |
これで、Ruby で Twitter API を使用するために必要なすべてのものが揃いました。次は、Twitter ラッパーをテストします。この例では、IRB (Interactive Ruby Shell) と呼ばれるシェルを使用します。このシェルでは、Ruby コマンドを実行して Ruby 言語をリアルタイムで試すことができます。IRB には多数の機能が備わっていますが、ここでは IRB を単純な実験のために使用します。
リスト 1 に記載する IRM とのセッションは、読みやすくするために、3 つのセクションに分かれています。最初のセクションの行
001 と 002 では、必要なランタイム要素をインポートして、環境を準備しているだけです (require
メソッドが指定のライブラリーをロードして実行します)。次の行 003 に、Twitter gem を使用して IBM
developerWorks からの最新ツイートを表示する方法を示しています。この行に示されているように、ツイートを表示するには Client::Timeline モジュールの user_timeline
メソッドを使用します。この最初の例で実演しているのは、Ruby の「メソッド・チェーン」機能です。user_timeline メソッドは 20 のツイートからなる配列を返します。この配列を first
メソッドにつなぐことで、配列から最初のツイートを抽出します (first は Array クラスのメソッドです)。この 1 つのツイートからテキスト・フィールドを抽出し、それを puts メソッドによって出力に書き出します。
次のセクションの行 004 で使用しているユーザー定義の location
フィールドは、有用な位置情報も、有用ではない位置情報も入力できるフリー・フォームのフィールドです。この例で User モジュールが取得するユーザー情報は、この location フィールドによって制約されます。
最後のセクションの行 005 以降では、Twitter::Search
モジュールを詳しく調べています。この検索モジュールは、Twitter を検索するための極めてリッチなインターフェースを提供します。この例では、最初に検索インスタンスを作成し
(行 005)、次の行 006 でその検索内容を指定します。ここで検索対象としているのは、ユーザー「LulzSec」に送信されたツイートのうち「why」という単語が含まれる最新のツイートです。検索結果のリストは、短く編集してあります。検索は、検索インスタンスは定義されたフィルターを保持するという点で固定的です。これらのフィルターをクリアするには、search.clear を実行します。
リスト 1. IRB での Twitter API の実験
$ irb
irb(main):001:0> require "rubygems"
=> true
irb(main):002:0> require "twitter"
=> true
irb(main):003:0> puts Twitter.user_timeline("developerworks").first.text
dW Twitter is saving #IBM over $600K per month: will #Google+ add to that? >
http://t.co/HiRwir7 #Tech #webdesign #Socialmedia #webapp #app
=> nil
irb(main):004:0> puts Twitter.user("MTimJones").location
Colorado, USA
=> nil
irb(main):005:0> search = Twitter::Search.new
=> #<Twitter::Search:0xb7437e04 @oauth_token_secret=nil,
@endpoint="https://api.twitter.com/1/",
@user_agent="Twitter Ruby Gem 1.6.0",
@oauth_token=nil, @consumer_secret=nil,
@search_endpoint="https://search.twitter.com/",
@query={:tude=>[], :q=>[]}, @cache=nil, @gateway=nil, @consumer_key=nil,
@proxy=nil, @format=:json, @adapter=:net_http<
irb(main):006:0> search.containing("why").to("LulzSec").
result_type("recent").each do |r| puts r.text end
@LulzSec why not stop posting <bleep> and get a full time job! MYSQLi isn't
hacking you <bleep>.
...
irb(main):007:0>
|
続いて、Twitter ユーザーのスキーマを調べてみます。それには IRB を使うこともできますが、Twitter
ユーザーの詳細を簡潔に示すために、結果のフォーマットを変更することにします。リスト 2 に、ユーザー構造の出力結果を記載します。この構造は Ruby の
Hashie::Mash です。Hashie::Mash
が役に立つ理由は、この構造ではオブジェクトにハッシュ・キーへのアクセサー (メソッドのようなもの) を持たせることができるためです
(つまり、オープン・オブジェクトなのです)。リスト 2 を見るとわかるように、このオブジェクトには (ジオコード情報を伴う)
現在のユーザー・ステータスをはじめ、豊富な情報 (ユーザー固有の情報とレンダリング情報) が含まれます。ツイートにも同じく大量の情報が含まれていて、user_timeline クラスによってこの情報を生成できることは簡単に想像できるはずです。
リスト 2. Twitter ユーザーの分析 (Ruby の観点)
irb(main):007:0> puts Twitter.user("MTimJones")
<#Hashie::Mash
contributors_enabled=false
created_at="Wed Oct 08 20:40:53 +0000 2008"
default_profile=false default_profile_image=false
description="Platform Architect and author (Linux, Embedded, Networking, AI)."
favourites_count=1
follow_request_sent=nil
followers_count=148
following=nil
friends_count=96
geo_enabled=true
id=16655901 id_str="16655901"
is_translator=false
lang="en"
listed_count=10
location="Colorado, USA"
name="M. Tim Jones"
notifications=nil
profile_background_color="1A1B1F"
profile_background_image_url="..."
profile_background_image_url_https="..."
profile_background_tile=false
profile_image_url="http://a0.twimg.com/profile_images/851508584/bio_mtjones_normal.JPG"
profile_image_url_https="..."
profile_link_color="2FC2EF"
profile_sidebar_border_color="181A1E" profile_sidebar_fill_color="252429"
profile_text_color="666666"
profile_use_background_image=true
protected=false
screen_name="MTimJones"
show_all_inline_media=false
status=<#Hashie::Mash
contributors=nil coordinates=nil
created_at="Sat Jul 02 02:03:24 +0000 2011"
favorited=false
geo=nil
id=86978247602094080 id_str="86978247602094080"
in_reply_to_screen_name="AnonymousIRC"
in_reply_to_status_id=nil in_reply_to_status_id_str=nil
in_reply_to_user_id=225663702 in_reply_to_user_id_str="225663702"
place=<#Hashie::Mash
attributes=<#Hashie::Mash>
bounding_box=<#Hashie::Mash
coordinates=[[[-105.178387, 40.12596],
[-105.034397, 40.12596],
[-105.034397, 40.203495],
[-105.178387, 40.203495]]]
type="Polygon"
>
country="United States" country_code="US"
full_name="Longmont, CO"
id="2736a5db074e8201"
name="Longmont" place_type="city"
url="http://api.twitter.com/1/geo/id/2736a5db074e8201.json"
>
retweet_count=0
retweeted=false
source="web"
text="@AnonymousIRC @anonymouSabu @LulzSec @atopiary @Anonakomis Practical reading
for future reference... LULZ \"Prison 101\" http://t.co/sf8jIH9" truncated=false
>
statuses_count=79
time_zone="Mountain Time (US & Canada)"
url="http://www.mtjones.com"
utc_offset=-25200
verified=false
>
=> nil
irb(main):008:0>
|
以上で、クイック・ツアーは終わりです。次は、Ruby と Twitter API を使用してデータを収集して視覚化するために使用できる単純なスクリプトを検討していきます。その過程で、実行回数の制限や認証といった Twitter の概念についても説明します。
以降のセクションでは、Twitter API を使用して入手可能なデータを収集して表示するスクリプトをいくつか記載します。これらのスクリプトでは簡潔さに重点が置かれていますが、スクリプトを拡張および組み合わせることで、新しい機能を作成することができます。さらに、このセクションで取り上げる Twitter gem API の機能はほんの一部に過ぎません。この API には他にも多数の機能が用意されています。
注意すべき点として、Twitter API では、クライアントが 1 時間あたりに行える呼び出しの数は限られています。つまり、Twitter ではリクエストの実行回数に制限を設けているので (現在、1 時間あたり最大 150 に制限)、この制限を超えて実行するとエラー・メッセージが表示され、新しいリクエストを送信できるようになるまで待たなければなりません。
リスト 2 で見たように、Twitter ユーザーごとに大量のユーザー関連の情報が使用できるようになっていますが、この情報にアクセスできるのは、そのユーザーが保護されていない場合のみです。これから、手際よくユーザーのデータを抽出して表示する方法を調べます。
リスト 3 に記載する単純な Ruby スクリプトは、(ユーザー名を基準に)
ユーザーの情報を検索し、そのなかから有用な要素を抽出して出力します。必要に応じて Ruby の to_s メソッドを使用して値をストリングに変換します。重要な点は、ます始めにユーザーが保護されていないことを確認することです。ユーザーが保護されている場合、そのユーザーのデータにはアクセスすることができません。
リスト 3. Twitter ユーザーのデータを抽出する単純なスクリプト (user.rb)
#!/usr/bin/env ruby
require "rubygems"
require "twitter"
screen_name = String.new ARGV[0]
a_user = Twitter.user(screen_name)
if a_user.protected != true
puts "Username : " + a_user.screen_name.to_s
puts "Name : " + a_user.name
puts "Id : " + a_user.id_str
puts "Location : " + a_user.location
puts "User since : " + a_user.created_at.to_s
puts "Bio : " + a_user.description.to_s
puts "Followers : " + a_user.followers_count.to_s
puts "Friends : " + a_user.friends_count.to_s
puts "Listed Cnt : " + a_user.listed_count.to_s
puts "Tweet Cnt : " + a_user.statuses_count.to_s
puts "Geocoded : " + a_user.geo_enabled.to_s
puts "Language : " + a_user.lang
if (a_user.url != nil)
puts "URL : " + a_user.url.to_s
end
if (a_user.time_zone != nil)
puts "Time Zone : " + a_user.time_zone
end
puts "Verified : " + a_user.verified.to_s
puts
tweet = Twitter.user_timeline(screen_name).first
puts "Tweet time : " + tweet.created_at
puts "Tweet ID : " + tweet.id.to_s
puts "Tweet text : " + tweet.text
end
|
このスクリプトを呼び出すには、これが実行可能なスクリプトであることを確認した上で (chmod +x
user.rb)、ユーザーを指定して呼び出します。リスト 4 は、ユーザーとして「developerworks」を指定した場合の結果です。この結果には、ユーザーの情報と現在のステータス (最新のツイートの情報) が示されています。Twitter でのフォロワーの定義は、そのユーザーをフォローしている別のユーザーですが、そのユーザーがフォローする相手のユーザーについては、友だちと呼ぶことに注意してください。
リスト 4. user.rb による出力例
$ ./user.rb developerworks Username : developerworks Name : developerworks Id : 16362921 Location : User since : Fri Sep 19 13:10:39 +0000 2008 Bio : IBM's premier Web site for Java, Android, Linux, Open Source, PHP, Social, Cloud Computing, Google, jQuery, and Web developer educational resources Followers : 48439 Friends : 46299 Listed Cnt : 3801 Tweet Cnt : 9831 Geocoded : false Language : en URL : http://bit.ly/EQ7te Time Zone : Pacific Time (US & Canada) Verified : false Tweet time : Sun Jul 17 01:04:46 +0000 2011 Tweet ID : 92399309022167040 Tweet text : dW Twitter is saving #IBM over $600K per month: will #Google+ add to that? > http://t.co/HiRwir7 #Tech #webdesign #Socialmedia #webapp #app |
今度は友だち (フォローしている相手) のことを調べてみましょう。友だちのデータを収集して、友だちにどれだけの人気があるかを調べます。それには、友だちを収集して、フォロワー数の順でソートします。そのためのスクリプトは、リスト 5 に記載するとおりの単純なものです。
このスクリプトでは、(ユーザー名を基準に) 分析したいユーザーを把握してから、ユーザー・ハッシュを作成します。Ruby のハッシュ (または、連想配列) とは、(単純な数値インデックスの代わりに) キーを定義してデータを格納できるデータ構造のことです。ハッシュを作成すると、そのハッシュには Twitter のユーザー名でインデックスが付けられ、ユーザーのフォロワー数が値として関連付けられます。このプロセスが友だちごとに単純に繰り返されて、それぞれのフォロワー数がハッシュに格納されます。そして最後にハッシュを (フォロワー数の降順で) ソートして、出力として書き出します。
リスト 5. 友だちの人気を調べるスクリプト (friends.rb)
#!/usr/bin/env ruby
require "rubygems"
require "twitter"
require 'google_chart'
name = String.new ARGV[0]
user = Hash.new
# Iterate friends, hash their followers
friends = Twitter.friend_ids(name)
friends.ids.each do |fid|
f = Twitter.user(fid)
# Only iterate if we can see their followers
if (f.protected.to_s != "true")
user[f.screen_name.to_s] = f.followers_count
end
end
user.sort_by {|k,v| -v}.each { |user, count| puts "#{user}, #{count}" }
|
リスト 6 は、リスト 5 の friends スクリプトによる出力例です。この出力は、スペースを節約するために一部省略されていますが、ご覧のとおり、私が直接フォローしている Twitter ユーザーのなかで人気の高いのは ReadWriteWeb (RWW) と Playstation です。
リスト 6. リスト 5 の friends スクリプトによる画面出力
$ ./friends.rb MTimJones RWW, 1096862 PlayStation, 1026634 HarvardBiz, 541139 tedtalks, 526886 lifehacker, 146162 wandfc, 121683 AnonymousIRC, 117896 iTunesPodcasts, 82581 adultswim, 76188 forrester, 72945 googleresearch, 66318 Gartner_inc, 57468 developerworks, 48518 |
リスト 2 に示されているように、Twitter はさまざまな位置情報を提供します。location フィールドはユーザーが定義するフリー・フォームのフィールドで、オプションでジオコーディング・データを定義することができます。その一方、ユーザー定義のタイムゾーンも、フォロワーの実際の位置を知る手掛かりとなります。
これから紹介する例では、Twitter フォロワーのタイムゾーン・データを抽出するマッシュアップを作成し、このデータを、Google Chart を使用してグラフで表示します。Google Chart は、Web 上で各種のグラフ作成を可能にする興味深いプロジェクトです。グラフのタイプとデータを HTTP リクエストとして定義すると、そのレスポンスとして直接ブラウザーにグラフがレンダリングされます。Google Chart を使用するための Ruby gem をインストールするには、以下の内容をコマンドラインで実行します。
$ gem install gchartrb |
リスト 7 に、タイムゾーン・データを抽出し、続いて Google Chart リクエストを作成するスクリプトを記載します。これまでのスクリプトとは異なり、このスクリプトを使用するには最初に Twitter で認証されなければなりません。そのためには、アプリケーションを Twitter に登録し、キーとトークンのセットを入手する必要があります。これらのトークンをリスト 7 のスクリプトに適用すれば、データを抽出できるようになります。この簡単な登録プロセスについての詳細は、「参考文献」を参照してください。
このスクリプトは同じようなパターンに従って、あるユーザーのユーザー名を受け入れ、そのユーザーのフォロワーを繰り返し処理します。現行のフォロワーのタイムゾーンが抽出されて、それが
tweetlocation ハッシュに格納されます。最初にこのキーがハッシュに含まれているかどうかをテストし、含まれている場合には、キーのカウンターをインクリメントすることに注意してください。また、抽出されたタイムゾーンごとの合計数を記録し、後でパーセンテージを算出できるようにします。
スクリプトの最後の部分では、Google 円グラフの URL を作成します。まず、新規 PieChart
を作成し、オプション (サイズ、タイトル、3D にするかどうか)
を指定します。次に、タイムゾーン・ハッシュを繰り返し処理して、グラフのデータとして各タイムゾーンのストリング (& 記号を削除) と、そのタイムゾーンが全体に占めるパーセンテージを出力します。
リスト 7. Twitter フォロワーのタイムゾーンを示す円グラフを作成するスクリプト (followers-location.rb)
#!/usr/bin/env ruby
require "rubygems"
require "twitter"
require 'google_chart'
screen_name = String.new ARGV[0]
tweetlocation = Hash.new
timezones = 0.0
# Authenticate
Twitter.configure do |config|
config.consumer_key = '<consumer_key>'
config.consumer_secret = '<consumer_secret>'
config.oauth_token = '<oath_token>'
config.oauth_token_secret = '<oath_token_secret>'
end
cursor = "-1"
# Loop through all pages
while cursor != 0 do
# Iterate followers, hash their location
followers = Twitter.follower_ids(screen_name, :cursor=>cursor)
followers.ids.each do |fid|
f = Twitter.user(fid)
loc = f.time_zone.to_s
if (loc.length > 0)
if tweetlocation.has_key?(loc)
tweetlocation[loc] = tweetlocation[loc] + 1
else
tweetlocation[loc] = 1
end
timezones = timezones + 1.0
end
end
cursor = followers.next_cursor
end
# Create a pie chart
GoogleChart::PieChart.new('650x350', "Time Zones", false ) do |pc|
tweetlocation.each do |loc,count|
pc.data loc.to_s.delete("&"), (count/timezones*100).round
end
puts pc.to_url
end
|
リスト 7 のスクリプトを実行するには、スクリプトに Twitter ユーザー名を指定し、それによって生成された URL をブラウザーにコピー・アンド・ペーストします。リスト 8 にこのプロセスと、結果として生成された URL を記載します。
リスト 8. followers-location スクリプトの呼び出し (この結果は実際には 1 行です)
$ ./followers-location.rb MTimJones http://chart.apis.google.com/chart?chl=Seoul|Santiago|Paris|Mountain+Time+(US++Canada)| Madrid|Central+Time+(US++Canada)|Warsaw|Kolkata|London|Pacific+Time+(US++Canada)| New+Delhi|Pretoria|Quito|Dublin|Moscow|Istanbul|Taipei|Casablanca|Hawaii|Mumbai| International+Date+Line+West|Tokyo|Ulaan+Bataar|Vienna|Osaka|Alaska|Chennai|Bern| Brasilia|Eastern+Time+(US++Canada)|Rome|Perth|La+Paz &chs=650x350&chtt=Time+Zones&chd=s:KDDyKcKDOcKDKDDDDDKDDKDDDDOKK9DDD&cht=p $ |
リスト 8 の URL をブラウザーに貼り付けると、図 1 に示す結果が得られます。
図 1. Twitter フォロワーの位置を示す円グラフ
Twitter の大量のデータをマイニングすることで、ユーザーの行動に関するいくつかの要素もわかります。そのデータ・マイニングの単純な例として、Twitter ユーザーがツイートする時刻の分析、そしてツイートするために使用するアプリケーションの分析の 2 つが挙げられます。以降に記載する 2 つの単純なスクリプトによって、これらの情報を抽出してグラフ化することができます。
リスト 9 に記載するスクリプトは、特定のユーザーによるツイートを繰り返し処理した後 (user_timeline メソッドを使用します)、ツイートごとに、そのツイートが行われた曜日を抽出します。ここでも単純なハッシュを使用して曜日ごとの数を累積し、前のタイムゾーンの例と同じように Google Chart を使用して棒グラフを生成します。ハッシュのデフォルト値を設定することで、ハッシュが未定義の場合の戻り値を指定していることにも注意してください。
リスト 9. ツイートが行われた曜日を示す棒グラフを作成するスクリプト (tweet-days.rb)
#!/usr/bin/env ruby
require "rubygems"
require "twitter"
require "google_chart"
screen_name = String.new ARGV[0]
dayhash = Hash.new
# Initialize to avoid a nil error with GoogleCharts (undefined is zero)
dayhash.default = 0
timeline = Twitter.user_timeline(screen_name, :count => 200 )
timeline.each do |t|
tweetday = t.created_at.to_s[0..2]
if dayhash.has_key?(tweetday)
dayhash[tweetday] = dayhash[tweetday] + 1
else
dayhash[tweetday] = 1
end
end
GoogleChart::BarChart.new('300x200', screen_name, :vertical, false) do |bc|
bc.data "Sunday", [dayhash["Sun"]], '00000f'
bc.data "Monday", [dayhash["Mon"]], '0000ff'
bc.data "Tuesday", [dayhash["Tue"]], '00ff00'
bc.data "Wednesday", [dayhash["Wed"]], '00ffff'
bc.data "Thursday", [dayhash["Thu"]], 'ff0000'
bc.data "Friday", [dayhash["Fri"]], 'ff00ff'
bc.data "Saturday", [dayhash["Sat"]], 'ffff00'
puts bc.to_url
end
|
developerWorks アカウントに対してリスト 9 の tweet-days スクリプトを実行した結果は、図 2 のとおりです。この図に示されているように、developerWorks アカウントの場合、ツイートが最も盛んに行われる傾向がある曜日は水曜日で、最も少ないのは日曜日となっています。
図 2. 曜日ごとのツイート数を相対的に示す棒グラフ
次に記載するスクリプトは、特定のユーザーがどのサービスからツイートしたのかを判断するものです。ツイートするにはいくつかの方法がありますが、このスクリプトはそのすべてについてコーディングしているわけではありません。リスト 10 に示されているように、同様のパターンで特定のユーザーのユーザー・タイムラインを抽出してから、ツイートする際に使用したサービスの名前をハッシュに格納します。このハッシュは、後で Google Chart で単純な円グラフを作成してデータを視覚化するときに使用します。
リスト 10. あるユーザーがツイートする際に使用したサービスを示す円グラフを作成するスクリプト (tweet-source.rb)
#!/usr/bin/env ruby
require "rubygems"
require "twitter"
require 'google_chart'
screen_name = String.new ARGV[0]
tweetsource = Hash.new
timeline = Twitter.user_timeline(screen_name, :count => 200 )
timeline.each do |t|
if (t.source.rindex('blackberry')) then
src = 'Blackberry'
elsif (t.source.rindex('snaptu')) then
src = 'Snaptu'
elsif (t.source.rindex('tweetmeme')) then
src = 'Tweetmeme'
elsif (t.source.rindex('android')) then
src = 'Android'
elsif (t.source.rindex('LinkedIn')) then
src = 'LinkedIn'
elsif (t.source.rindex('twitterfeed')) then
src = 'Twitterfeed'
elsif (t.source.rindex('twitter.com')) then
src = 'Twitter.com'
else
src = t.source
end
if tweetsource.has_key?(src)
tweetsource[src] = tweetsource[src] + 1
else
tweetsource[src] = 1
end
end
GoogleChart::PieChart.new('320x200', "Tweet Source", false) do |pc|
tweetsource.each do|source,count|
pc.data source.to_s, count
end
puts "\nPie Chart"
puts pc.to_url
end
|
図 3 に示すのは、ある Twitter ユーザーがツイートする際に使用したサービスの割合を示す興味深い結果をグラフにしたものです。最もよく使用されているのは従来の Twitter Web サイトであり、次いで、携帯電話のアプリケーションがよく使用されています。
図 3. ある Twitter ユーザーがツイートする際に使用したサービスの割合を示す円グラフ
Twitter は、(多数のノードとエッジで構成される) 1 つのグラフを形作る壮大なユーザー・ネットワークです。これまで紹介したスクリプトで見てきたように、連絡先を繰り返し処理することは簡単です。そしてさらに、連絡先の連絡先を繰り返し処理することも簡単です。こうしたレベルであっても、このような繰り返し処理によって大規模なグラフの基礎が形成されます。
グラフを描画するためのツールとして私が選んだのは、GraphViz というグラフ描画ソフトウェアです。Ubuntu では、以下の内容をコマンドラインで実行することで、簡単にこのツールをインストールすることができます。
$ sudo apt-get install graphviz |
リスト 11 に記載するスクリプトは、ユーザーのフォロワーを繰り返し処理し、さらにフォロワーのフォロワーを繰り返し処理します。このパターンの中でこれまでのスクリプトと本質的に異なるところは、GraphViz の dot フォーマット・ファイルを作成する部分のみです。GraphViz は単純なスクリプト・フォーマットを使用してグラフを定義するので、これらのグラフを Twitter ユーザーの列挙の一部として出力します。以下のとおり、単にノードの関係を指定するだけで、グラフを定義することができます。
リスト 11. Twitter フォロワーのグラフを描画するスクリプト (followers-graph.rb)
#!/usr/bin/env ruby
require "rubygems"
require "twitter"
require 'google_chart'
screen_name = String.new ARGV[0]
tweetlocation = Hash.new
# Authenticate
Twitter.configure do |config|
config.consumer_key = '<consumer_key>'
config.consumer_secret = '<consumer_secret>'
config.oauth_token = '<oath_token>'
config.oauth_token_secret = '<oath_token_secret>'
end
my_file = File.new("graph.dot", "w")
my_file.puts "graph followers {"
my_file.puts " node [ fontname=Arial, fontsize=6, penwidth=4 ];"
# Get the first page of followers
followers = Twitter.follower_ids(screen_name, :cursor=> -1 )
# Iterate the followers returned in the Array (max 10).
followers.ids[0..[5,followers.ids.length].min].each do |fid|
f = Twitter.user(fid)
# Only iterate if we can see their followers
if (f.protected.to_s != "true")
my_file.puts " \"" + screen_name + "\" -- \"" + f.screen_name.to_s + "\""
# Get the first page of their followers
followers2 = Twitter.follower_ids(f.screen_name, :cursor => -1 )
# Iterate the followers returned in the Array (max 10).
followers2.ids[0..[5,followers2.ids.length].min].each do |fid2|
f2 = Twitter.user(fid2)
my_file.puts " \"" + f.screen_name.to_s + "\" -- \"" +
f2.screen_name.to_s + "\""
end
end
end
my_file.puts "}"
|
あるユーザーに対してリスト 11 のスクリプトを実行すると dot ファイルが作成されるので、GraphViz を使用して、その dot
ファイルからグラフの画像を生成します。最初に Ruby スクリプトを呼び出してグラフ・データを収集し (graph.dot として保存)、それから GraphViz
を使用してグラフの画像を生成します (ここで使用している circo は、円形レイアウトを指定します)。この画像を生成するプロセスは、以下のように定義されます。
$ ./followers-graph.rb MTimJones $ circo graph.dot -Tpng -o graph.png |
図 4 に、生成されたグラフの画像を示します。Twitter グラフは大規模になりがちなので、ここでは列挙するユーザーとそのフォロワーの数を最小限にして (リスト 11 では min 関数を使用することで)、グラフを小さくしていることに注意してください。
図 4. Twitter フォロワー・グラフの例 (ほんの一部)
ジオロケーションを利用できる場合、Twitter はユーザーとユーザーのツイートに関するジオロケーション・データを収集します。このデータを構成する緯度と経度の情報は、ユーザーの正確な位置、あるいはツイートが送信された正確な位置を突き止めるために使用することができます。この情報は検索にも組み込めるので、定義した位置または自分の位置を基準にして、場所または人を特定することもできます。
(プライバシー上の理由により) すべてのユーザーまたはツイートについてジオロケーションを利用できるというわけではありませんが、この情報によって Twitter エクスペリエンス全体に興味深い側面がもたらされます。そこで、ジオロケーション・データの視覚化を行うスクリプトと、ジオロケーション・データを使って検索を行うスクリプトを紹介します。
最初のスクリプト (リスト 12 を参照) でユーザーから取得するデータは、緯度と経度です (リスト 2 に示されていた境界ボックスを思い出してください)。この境界ボックスは、ユーザーに対して描画する領域を定義する多角形ですが、このデータを単純化して 1 つの点を使用します。このデータにより、単純な HTML ファイル内に単純な JavaScript 関数を生成します。この JavaScript コードが Google マップとインターフェースを取り、(Twitter ユーザーから抽出した緯度と経度のデータを基に) 該当する位置の航空写真による地図を表示します。
リスト 12. ユーザーの地図を作成する Ruby スクリプト (where-am-i.rb)
#!/usr/bin/env ruby
require "rubygems"
require "twitter"
require 'google_chart'
Twitter.configure do |config|
config.consumer_key = '<consumer_key>'
config.consumer_secret = '<consumer_secret>'
config.oauth_token = '<oauth_token>'
config.oauth_token_secret = '<oauth_token_secret>'
end
screen_name = String.new ARGV[0]
a_user = Twitter.user(screen_name)
if a_user.geo_enabled == true
long = a_user.status.place.bounding_box.coordinates[0][0][0];
lat = a_user.status.place.bounding_box.coordinates[0][0][1];
my_file = File.new("test.html", "w")
my_file.puts "<!DOCTYPE html>"
my_file.puts "<html><head>"
my_file.puts "<meta name=\"viewport\" content=\"initial-scale=1.0, "
my_file.puts "user-scalable=no\" />"
my_file.puts "<style type=\"text/css\">"
my_file.puts "html { height: 100% }"
my_file.puts "body { height: 100%; margin: 0px; padding: 0px }"
my_file.puts "#map_canvas { height: 100% }"
my_file.puts "<style>"
my_file.puts "<script type=\"text/javascript\""
my_file.puts "src=\"http://maps.google.com/maps/api/js?sensor=false\">"
my_file.puts "<script>"
my_file.puts "<script type=\"text/javascript\">"
my_file.puts "function initialize() {"
my_file.puts "var latlng = new google.maps.LatLng(" + lat.to_s + ", " + long.to_s + ");"
my_file.puts "var myOptions = {"
my_file.puts "zoom: 12,"
my_file.puts "center: latlng,"
my_file.puts "mapTypeId: google.maps.MapTypeId.HYBRID"
my_file.puts "};"
my_file.puts "var map = new google.maps.Map(document.getElementById(\"map_canvas\"),"
my_file.puts "myOptions);"
my_file.puts "}"
my_file.puts "<script>"
my_file.puts "<head>"
my_file.puts "<body onload=\"initialize()\">"
my_file.puts "<div id=\"map_canvas\" style=\"width:100%; height:100%\"<>/div>"
my_file.puts "<body>"
my_file.puts "<html>"
else
puts "no geolocation data available."
end
|
リスト 12 のスクリプトは、以下のように簡単に実行することができます。
$ ./where-am-i.rb MTimJones |
実行した結果として生成された HTML ファイルは以下のようにしてブラウザーでレンダリングされます。
$ firefox test.html |
上記のスクリプトは、位置情報を利用できなければ失敗しますが、正常に実行された場合には HTML ファイルが生成されます。ブラウザーはそのファイルを読み取ることで、地図をレンダリングすることができます。図 5 に、ブラウザーでレンダリングされた地図の画像を示します。ここに示されているのは、米国コロラド州北部のFront Range の一部です。
図 5. リスト 12 のスクリプトによってレンダリングされた画像の例
ジオロケーションを使って Twitter を検索し、特定の位置に関連する Twitter ユーザーとツイートを特定することもできます。Twitter Search API では、ジオコーディング情報を使用して検索結果を絞り込めるようになっています。リスト 13 に記載するのは、ユーザーの緯度と経度のデータを抽出し、そのデータを使って、該当する位置の半径 5 マイル以内で送信されたツイートを取得する例です。
リスト 13. 緯度と経度のデータを利用することによる、近くで送信されたツイートの検索 (tweets-local.rb)
#!/usr/bin/env ruby
require "rubygems"
require "twitter"
Twitter.configure do |config|
config.consumer_key = '<consumer_key>'
config.consumer_secret = '<consumer_secret>'
config.oauth_token = '<oauth_token>'
config.oauth_token_secret = '<oauth_token_secret>'
end
screen_name = String.new ARGV[0]
a_user = Twitter.user(screen_name)
if a_user.geo_enabled == true
long = a_user.status.place.bounding_box.coordinates[0][0][0]
lat = a_user.status.place.bounding_box.coordinates[0][0][1]
Array tweets = Twitter::Search.new.geocode(lat, long, "5mi").fetch
tweets.each do |t|
puts t.from_user + " | " + t.text
end
end
|
リスト 13 のスクリプトを実行した結果をリスト 14 に記載します。このリストには、指定された範囲内で頻繁にツイートしているユーザーのものだけが示されています。
リスト 14. 私がいる位置の半径 5 マイル以内で送信されたツイートの表示
$ ./tweets-local.rb MTimJones Breesesummer | @DaltonOls did he answer u LongmontRadMon | 60 CPM, 0.4872 uSv/h, 0.6368 uSv/h, 2 time(s) over natural radiation graelston | on every street there is a memory; a time and place we can never be again. Breesesummer | #I'minafight with @DaltonOls to see who will marry @TheCodySimpson I will marry him!!! :/ _JennieJune_ | ok I'm done, goodnight everyone! Breesesummer | @DaltonOls same _JennieJune_ | @sylquejr sleep well! Breesesummer | @DaltonOls ok let's see what he says LongmontRadMon | 90 CPM, 0.7308 uSv/h, 0.7864 uSv/h, 2 time(s) over natural radiation Breesesummer | @TheCodySimpson would u marry me or @DaltonOls natcapsolutions | RT hlovins: The scientific rebuttal to the silly Forbes release this morning: Misdiagnosis of Surface Temperatu... http://bit.ly/nRpLJl $ |
この記事では、Ruby 言語を使用して Twitter からデータを抽出する数々の単純なスクリプトを紹介しました。記事では、基本的な概念を説明する単純なスクリプトを作成して提示することに重点を置きましたが、データを抽出する以外にも Twitter API ではさまざまなことが可能です。この Twitter API を使用して、例えば友だちのネットワークを探索し、自分にとって興味深い、最も人気のある Twitter ユーザーを探し出すこともできます。興味深い領域としては、ツイート自体のマイニングも挙げられます。ジオロケーション・データを使用してツイートを検索すれば、位置をベースに行動や出来事 (インフルエンザの大流行など) を理解することができます。この記事では表面をかじっただけに過ぎませんが、皆さん独自のマッシュアップを作って、この記事にコメントをお寄せください。Ruby と Twitter gem を使用すれば、それぞれのデータ・マイニングの必要を満たす有益なマッシアップやダッシュボードを簡単に開発することができます。
学ぶために
- Ruby 言語の公式 Web
サイトは、Ruby のニュース、情報、リリース、資料、そして Ruby 言語のコミュニティー・サポートをまとめて調べられる情報源です。Web フレームワーク (Ruby on Rails など) で Ruby がますます使われるようになっていることから、最新のセキュリティー上の弱点とそれに対するソリューションも学べるようになっています。
- Github social coding サイトに、Twitter gem の公式ソースが用意されています。このサイトで、Ruby Twitter gem のソース、資料、メーリング・リストにアクセスできます。
- Twitter APIの特定の要素を使用するには、Twitter アプリケーションを登録する必要があります。登録は無料です。登録した後は、この API のさらに有用な要素にアクセスできるようになります。
- Google
Maps JavaScript API チュートリアルでは、Google Maps を使用して、ユーザー提供のジオロケーション・データで各種の地図をレンダリングする方法を説明しています。この記事で使用した JavaScript は、このチュートリアルに記載されている「Hello World」の例に基づいています。
- developerWorks Open source ゾーンには、オープソースのツールおよびオープンソース技術の使用方法に関する情報が豊富に揃っています。
- Twitter での developerWorks:
developerWorks をフォローしてください。この記事の著者については、M. Tim Jones でフォローできます。
- developerWorks オンデマンド・デモ: 初心者向けの製品のインストールおよびセットアップから熟練開発者向けの高度な機能に至るまで、さまざまに揃ったデモを見て、学んでください。
製品や技術を入手するために
- John Nunemaker によって開発された Twitter Ruby gem は、Ruby 言語に巧みに統合する、Twitter サービスへの価値あるインターフェースとなります。
- Google Chart API は、さまざまなスタイルとオプションを使って複雑でリッチなグラフを作成できる、便利なサービスです。このサービスの API を使って URL を指定すると、Google サイトでグラフがレンダリングされます。
- Google Chart API Ruby ラッパーは、Google Chart API に対する Ruby インターフェースとなり、Ruby で有効なグラフを作成できるようにします。
- ご自分に最適な方法で IBM
製品を評価してください。評価の方法としては、製品の試用版をダウンロードすることも、オンラインで製品を試してみることも、クラウド環境で製品を使用することもできます。また、SOA Sandbox では、数時間でサービス指向アーキテクチャーの実装方法を効率的に学ぶことができます。
議論するために
- developerWorks コミュニティー: ここでは他の developerWorks ユーザーとのつながりを持てる他、開発者が主導するブログ、フォーラム、グループ、ウィキを調べることができます。

M. Tim Jones は組み込みソフトウェアのエンジニアであり、『Artificial Intelligence: A Systems Approach』、『GNU/Linux Application Programming』(現在、第 2 版です) や『AI Application Programming』(こちらも現在、第 2 版です)、それに『BSD Sockets Programming from a Multilanguage Perspective』などの著者でもあります。技術的な経歴は静止軌道衛星用のカーネル開発から、組み込みシステム・アーキテクチャーやネットワーク・プロトコル開発まで、広範にわたっています。彼はコロラド州ロングモン在住で、Intel に勤務するプラットフォーム・アーキテクトであり、執筆活動も行っています。