使用Ruby和Twitter來進行數(shù)據(jù)挖掘
2008年10月,我像許多人一樣滿懷好奇地創(chuàng)建了一個Twitter帳戶。像大多數(shù)人一樣,我與一些朋友建立了連接,做一些隨機的搜索來更好地理解這一服務。使用140個字符來進行溝通,這看起來好像不太可能是一個受歡迎的想法,但一件無關的事情卻讓我看到了Twitter的真正價值所在。
2009年7月初,我的網(wǎng)站托管服務提供商熄火了,在進行了一番隨意的網(wǎng)絡搜索后,我發(fā)現(xiàn)信息指向了西雅圖Fisher Plaza的一場火災,這場火是罪魁禍首。傳統(tǒng)的基于web的信息源更新很慢,沒有提供何時服務會恢復正常的指示。然而,在搜索了Twitter之后,我找到了一些個人帳戶對事件的描述,包括了現(xiàn)場實時發(fā)生的情況。例如,在我的托管服務恢復正常之前不久,就有一條消息說有柴油發(fā)電機位于大廈的外面。
當時我就意識到了Twitter的真正強大之處在于個人以及組織之間的公開的和實時的信息交流。然而,在這一表象下面,則是一個關于用戶行為的信息寶庫,以及在局部和全局層面上的發(fā)展趨勢。我使用了Ruby語言和Twitter gem這一Twitter的API包裝器來在簡單的腳本語境中探討挖掘的實現(xiàn),并說明了如何使用其他的web服務和應用來為數(shù)據(jù)的可視化構建一個簡單的混搭應用程序。
Twitter以及一些API
盡管早期的網(wǎng)絡涉及的是人-機器的交互,但現(xiàn)在的網(wǎng)絡已涉及機器-機器之間的交互,這種交互是使用web服務來支持的。大部分受歡迎的網(wǎng)站都有這樣的服務存在——從各種各樣的Google服務到LinkedIn、Facebook和Twitter等。通過web服務創(chuàng)建的API,外部的應用可以查詢或是操縱網(wǎng)站上的內(nèi)容。
web服務可以使用多種方式來實現(xiàn)。目前最流行的做法之一是表述性狀態(tài)轉移(Representational State Transfe, REST)。REST的一種實現(xiàn)是通過為人熟知的HTTP協(xié)議,允許HTTP作為RESTful架構的媒介存在(使用諸如GET、PUT、POST、DELETE一類的標準HTTP操作)。Twitter的API是作為這一媒介之上的一個抽象來進行開發(fā)的。在這一做法中,沒有涉及REST、HTTP或是XML或JSON一類的數(shù)據(jù)格式的知識,而是代之以清晰地整合到了Ruby語言中的基于對象的接口。
Ruby和Twitter的一個快速展示
讓我們來探討一下如何在Ruby中使用Twitter API。首先,我們需要獲取所需的資源,如果你像我一樣在用Ubuntu Linux®的話,就使用apt框架。
若要獲取最新的完整的Ruby分發(fā)版本(大約13MB的下載量),使用這一命令行:
- $ sudo apt-get install ruby1.9.1-full
接著使用gem實用程序來抓取Twitter gem:
- $ sudo gem install twitter
現(xiàn)在你已經(jīng)有了這一步驟所需的一切了,我們繼續(xù),測試一下Twitter的包裝器。這一示例使用一個名為交互式的Ruby外殼(Interactive Ruby Shell,IRB)的外殼程序,該外殼程序允許實時地執(zhí)行Ruby命令以及使用語言進行實驗。IRB有著非常多的功能,不過我們只用它來做一些簡單的實驗。
清單1展示了與IRB的一個會話,該會話被分成了三段以便于閱讀。第一段(001和002行)通過導入必需的運行時元素來做好環(huán)境方面的準備(require方法加載并執(zhí)行指定的庫)。接下來的一段(003行)說明的是使用Twitter gem來顯示從IBM® developerWorks®發(fā)出的最新tweet消息。如所展示的那樣,使用Client::Timeline模塊的user_timeline方法來顯示一條消息,這第一個例子說明了Ruby的“鏈方法”的功能。user_timeline方法返回一個有著20條消息的數(shù)組,接著鏈入到方法first中,這樣做是為了從數(shù)組中提取出第一條消息(first是Array類的一個方法),接著從這一條消息中提取出文本字段,通過puts方法把它放到輸出中。
接下來的一段(004行)使用了用戶定義的位置字段,這是一個不限形式的字段,用戶可以在其中提供有用的或是無用的位置信息。在這一例子中,User模塊抓取了位置字段所限定的用戶信息。
最后一段(從005行開始)研究了Twitter::Search模塊,這一搜索模塊提供了極其豐富的用來搜索Twitter的接口。在這一例子中,首先是創(chuàng)建一個搜索實例(005行),接著在006行指定一個搜索,搜 LulzSec用戶在最近發(fā)出的包含了why這一詞的消息,結果列表已經(jīng)過刪減和編輯。搜索設置會一直存在在那里,因為搜索實例保持著所定義的過濾條件,你可以通過執(zhí)行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來實現(xiàn)這一點,不過我重排了結果的格式,以便簡化對Twitter用戶的內(nèi)部結構的說明。清單2給出了用戶結構的輸出結果,這在Ruby中是一個Hashie::Mash。這一結構很有用,因為其允許對象有類方法的哈希鍵訪問器(公開的對象)。正如你從清單2中看到的那樣,這一對象包含了豐富的信息(用戶特定的以及渲染的信息),其中包括了當前的用戶狀態(tài)(帶有地理編碼信息)。一條tweet消息中也包含了大量的信息,你可以使用user_timeline類來輕松地可視化生成這一信息。
清單2. Twitter用戶的內(nèi)部解析結構(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>
這就是快速展示部分的內(nèi)容?,F(xiàn)在,我們來研究一些簡單的腳本,你可以在這些腳本中使用Ruby和Twitter API來收集和可視化數(shù)據(jù)。在這一過程中,你會了解到Twitter的一些概念,比如說身份驗證和頻率限制等。
挖掘Twitter數(shù)據(jù)
接下來的幾節(jié)內(nèi)容介紹幾個通過Twitter API來收集和呈現(xiàn)可用數(shù)據(jù)的腳本,這些腳本重點在于其簡易性,不過你可以通過擴展以及組合他們來創(chuàng)建新的功能。另外,本節(jié)內(nèi)容還會提到Twitter gem API,這一API中有著更多可用的功能。
需要注意的很重要的一點是,在指定的時間內(nèi),Twitter API只允許客戶做有限次的調用,這也就是Twitter的頻率限制請求(現(xiàn)在是一小時不超過150次),這意味著經(jīng)過某個次數(shù)的使用后,你會收到一個錯誤消息,并要求你在提交新的請求之前先做一段時間的等待。
用戶信息
回想一下清單2中的每個Twitter用戶的大量可用信息,只有在用戶不受保護的情況下這些信息才是可訪問的。我們來看一下如何以一種更便捷的方式來提取用戶的信息并呈現(xiàn)出來。
清單3給出了一個(基于用戶的界面顯示名稱)檢索用戶信息的簡單的Ruby腳本,然后顯示一些更有用的內(nèi)容,在需要時使用Ruby方法to_s來把值轉換成字符串。需要注意的是,首先用戶是不受保護的,否則的話是不能訪問到她/他的數(shù)據(jù)的。
清單3. 提取Twitter用戶數(shù)據(jù)的簡單腳本(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
- puts "URL : " + a_user.url.to_s
- puts "Time Zone : " + a_user.time_zone
- 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
若要調用這一腳本,需要確保其是可執(zhí)行的(chmod +x user.rb),使用一個用戶的名稱來調用它。清單4顯示了使用用戶developerworks調用的結果,給出了用戶的信息和當前狀態(tài)(最后一條tweet消息)。這里要注意的是,Twitter把關注你的人定義為followers(粉絲);而把你關注的人稱作friends(朋友)。
清單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
#p#
朋友的受歡迎情況
研究一下你的朋友(你關注的人),收集數(shù)據(jù)來了解一下他們的受歡迎程度。在這個例子中,收集朋友的數(shù)據(jù)并按照他們的粉絲數(shù)目來進行排序,這一簡單的腳本如清單5所示。
在這一腳本中,在了解了你要(基于界面顯示名稱)分析的用戶后,創(chuàng)建一個用戶哈希表,Ruby哈希(或是相關的數(shù)組)是一種可以允許你定義存儲鍵(而不是簡單的數(shù)值索引)的數(shù)據(jù)結構。接著,通過Twitter的界面名稱來索引這一哈希表,關聯(lián)值則是用戶的粉絲數(shù)目。這一過程簡單地遍歷你的朋友然后把他們的粉絲的數(shù)目放入哈希表中,接著(以降序)排列哈希表,然后把它放到輸出中。
清單5. 關于朋友的受歡迎程度的腳本(friends.rb)
- #!/usr/bin/env ruby
- require "rubygems"
- require "twitter"
- name = String.new ARGV[0]
- user = Hash.new
- # Iterate friends, hash their followers
- Twitter.friends(name).users.each do |f|
- # 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}" }
清單5中的朋友腳本的一個例子輸出如清單6所示。我刪減了輸出內(nèi)容以節(jié)省空間,不過你可以看到,在我的直接網(wǎng)絡中,ReadWriteWeb(RWW)和Playstation是很受歡迎的Twitter用戶。
清單6. 清單5中的朋友腳本的界面輸出
- $ ./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提供了豐富的位置信息,有一個不限形式、用戶定義的、可選用地理編碼數(shù)據(jù)的位置字段。不過,用戶設定的時區(qū)也可以為粉絲的實際位置提供線索。
在這一例子中,你要構建一個混搭應用程序來從Twitter粉絲中提取時區(qū)數(shù)據(jù),然后使用Google Charts來可視化這一數(shù)據(jù)。Google Charts是一個非常有意思的項目,其允許你通過網(wǎng)絡來構建各種各樣不同類型的圖表;把圖表的類型和數(shù)據(jù)定義成HTTP請求,直接在瀏覽器中渲染作為響應的結果。若要安裝用于Google Charts的Ruby gem,使用下面的命令行:
- $ gem install gchartrb
清單7提供的腳本提取時區(qū)數(shù)據(jù),接著構建Google Charts請求。首先,與之前的腳本不同,這一腳本需要你通過Twitter的身份驗證。若要做到這一點,你需要注冊一個Twitter應用,這會給你提供一組鍵值和令牌,這些令牌可以用在清單7的腳本中,這樣才能夠成功地取到數(shù)據(jù)。請參閱參考資料了解這一簡單過程的詳細情況。
按照相類似的模式,該腳本接受了一個界面名稱,然后遍歷該用戶的粉絲,從當前粉絲中提取時區(qū)并把它存放在tweetlocation哈希表中。需要注意的是,你先要檢測該鍵值是否已經(jīng)存在于哈希表中,若是的話,增加該鍵值的計數(shù)。你還可以記住所有時區(qū)的個數(shù),以用于后面的百分比的計算。
這一腳本的最后一部分內(nèi)容是構造Google Pie Chart的URL,創(chuàng)建一個新的PieChart,指定一些選項(大小、標題和是否為3D等);接著,遍歷時區(qū)哈希表,找出用于圖表的時區(qū)串的數(shù)據(jù)(刪去&符號)以及該時區(qū)計數(shù)與總數(shù)的百分比。
清單7.通過Twitter的時區(qū)來構建一個餅圖(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 = ''
- config.consumer_secret = ''
- config.oauth_token = '
- config.oauth_token_secret = ''
- end
- # Iterate followers, hash their location
- followers = Twitter.followers.users.each do |f|
- 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
- # 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
若要執(zhí)行清單7中的腳本,給它提供一個Twitter界面顯示名稱,然后把得出的URL拷貝并粘貼到瀏覽器中,清單8給出了這一過程及最終生成的URL。
清單8. 調用followers-location腳本(結果只是一行來的)
- $ ./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包含了大量的數(shù)據(jù),你可以通過挖掘這些數(shù)據(jù)來了解用戶行為的某些要素。兩個簡單例子將用來分析Twitter用戶何時發(fā)布消息以及通過什么應用來發(fā)布消息,你可以使用下面兩個簡單的腳本來提取并可視化這些信息。
清單9給出的腳本遍歷了某個特定用戶的tweet消息(使用user_timeline方法),然后從每條tweet消息中提取出該tweet消息形成的具體時間,一個簡單的哈希表被再次用來統(tǒng)計一周中每天的計數(shù),然后以與前面的時區(qū)例子相類似的方式使用Google Charts生成一個柱狀圖。
清單9. 構建tweet發(fā)布時間的柱狀圖(tweet-days.rb)
- #!/usr/bin/env ruby
- require "rubygems"
- require "twitter"
- require "google_chart"
- screen_name = String.new ARGV[0]
- dayhash = Hash.new
- 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
圖2提供了使用developerWorks帳戶來執(zhí)行清單9中的tweet-days腳本的結果,正如所展示的那樣,星期三是發(fā)布tweet消息最活躍的一條,最不活躍的是星期六和星期天。
圖2. 比較每天的tweet活躍程度的柱狀圖
接下來的腳本確定特定用戶通過哪一個來源發(fā)布tweet消息,你可以通過幾種方式來發(fā)布消息,這一腳本并未對每一種都做了編碼。如清單10所示,使用類似的模式來提取給定用戶的時間軸上的內(nèi)容,然后嘗試著解碼哈希表中的tweet消息的發(fā)出處。稍后這一哈希表會被用來創(chuàng)建一個簡單的餅圖,使用Google Charts來可視化數(shù)據(jù)。
清單10. 構建用戶的tweet消息源的餅圖(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用戶感興趣使用的tweet消息發(fā)布源,傳統(tǒng)的Twitter網(wǎng)站最常用到,隨后是移動電話應用。
圖3. Twitter用戶的tweet消息發(fā)布源的餅圖
#p#
反映粉絲情況的圖表
Twitter是一個龐大的用戶網(wǎng)絡,這些用戶形成了一個網(wǎng)絡圖。正如你通過腳本所看到的那樣,遍歷你的聯(lián)系人很容易,接著遍歷他們的聯(lián)系人也很容易。即使只是在這一級別上,這樣做也已建立起一張大圖的基本面。
為了可視化圖形,我選擇使用圖形可視化軟件GraphViz。在Ubuntu上,使用下面的命令行,你可以很容易就安裝好這一工具:
- $ sudo apt-get install graphviz
清單11中的腳本遍歷了用戶的粉絲,然后再遍歷這些粉絲他們的粉絲。這一模式中的唯一真正不同之處在于 GraphViz的DOT格式文件的構造,GraphViz使用簡單的腳本格式來定義圖形,這些圖形作為你列舉的Twitter用戶的組成部分出現(xiàn)。如清單所展示的那樣,可以簡單地通過指定節(jié)點的關系來定義圖形。
清單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 = ''
- config.consumer_secret = ''
- config.oauth_token = ''
- config.oauth_token_secret = ''
- end
- my_file = File.new("graph.dot", "w")
- my_file.puts "graph followers {"
- my_file.puts " node [ fontname=Arial, fontsize=6 ];"
- # Iterate followers, hash their location
- followers = Twitter.followers(screen_name, :count=>10 ).users.each do |f|
- # Only iterate if we can see their followers
- if (f.protected.to_s != "true")
- my_file.puts " \"" + screen_name + "\" -- \"" + f.screen_name.to_s + "\""
- followers2 = Twitter.followers(f.screen_name, :count =>10 ).users.each do |f2|
- my_file.puts " \"" + f.screen_name.to_s + "\" -- \"" +
- f2.screen_name.to_s + "\""
- end
- end
- end
- my_file.puts "}"
在某個用戶上執(zhí)行清單11的腳本,得出的結果放在一個dot文件中,接著使用GraphViz來生成圖像。首先調用Ruby腳本來收集圖形數(shù)據(jù)(存儲成graph.dot);接著使用GraphViz來生成圖像(這里用的是circo,該工具指定了一種圓形的布局)。生成圖像的過程定義如下:
- $ ./followers-graph.rb MTimJones
- $ circo graph.dot -Tpng -o graph.png
最終得出的圖像如圖4所示。需要注意的是,由于這一Twitter圖表可能會很大,因為我們通過盡量減少要列舉的用戶及其粉絲的數(shù)目來限制圖表的規(guī)模(通過清單11中的:count選項)。
圖4. Twitter粉絲圖例子(極端情況的子集)
位置信息
在功能啟用的情況下,Twitter收集你和你發(fā)出tweet消息的地理位置數(shù)據(jù)。這些由經(jīng)度和緯度信息組成的數(shù)據(jù)能夠用來精確地定位用戶的位置或者是tweet消息從何處發(fā)出。此外,把搜索和這些消息結合在一起,你就可以根據(jù)已定義的位置或是你所處的位置來識別出某些地方或是某些人。
并非所有的用戶或是tweet消息都啟用了地理位置功能(出于隱私原因),但這一信息是所有Twitter體驗當中的一個非常吸引人的方面。讓我們來看一個腳本,該腳本允許你可視化地理定位數(shù)據(jù),還有另一個腳本允許你使用這一數(shù)據(jù)來進行搜索。
第一個腳本(清單12所示)抓取用戶的經(jīng)度和緯度數(shù)據(jù)(回想一下清單2中的邊界框(bounding box)),盡管邊界框是一個定義代表了用戶區(qū)域的多邊形,但我做了簡化,只用了這一區(qū)域中的一個點。有了這一數(shù)據(jù),我在一個簡單的HMTL文件中生成了一個簡單的JavaScript函數(shù),這一JavaScript代碼與Google Maps接口,給出了這一位置的一個俯視地圖(給出提取自Twitter用戶的經(jīng)度和緯度數(shù)據(jù))。
清單12. 構造用戶地圖的Ruby腳本(where-am-i.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 = '<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, 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中的腳本執(zhí)行起來很簡單:
- $ ./where-am-i.rb MTimJones
最終得出的HTML文件可以通過瀏覽器來渲染,像這樣:
- $ firefox test.html
如果沒有可用的位置信息的話,這一腳本就會執(zhí)行失敗;不過如果執(zhí)行成功的話,就會生成一個HTML文件,瀏覽器可以讀入該文件來渲染出地圖。圖5給出了最終生成的地圖圖像,其顯示了美國科羅拉多州北部Front Range的部分地區(qū)。
圖5. 清單12中的腳本渲染圖像的例子
有了地理位置,你還可以通過搜Twitter來識別出與某個特定位置相關聯(lián)的Twitter用戶和tweet消息。Twitter搜索API允許使用地理編碼信息來限定搜索結果。下面清單13中的例子提取用戶的經(jīng)度和緯度,然后使用這些數(shù)據(jù)獲取該位置方圓5公里之內(nèi)的所有tweet消息。
清單13. 使用經(jīng)度和緯度數(shù)據(jù)來搜索局部地區(qū)的tweet消息(tweets-local.rb)
- #!/usr/bin/env ruby
- require "rubygems"
- require "twitter"
- Twitter.configure do |config|
- config.consumer_key = ''
- config.consumer_secret = ''
- config.oauth_token = ''
- config.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中的腳本的執(zhí)行結果顯示在清單14中,這是指定位置范圍內(nèi)的Twitter用戶發(fā)布的tweet消息的一個子集。
清單14. 查詢我所在位置方圓5公里之內(nèi)的這一局部地區(qū)的tweet消息。
- $ ./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
- $
繼續(xù)深入
本文給出了一些簡單的腳本,這些腳本使用Ruby語言來從Twitter中提取數(shù)據(jù),文章的重點放在用來說明一些基本概念的腳本的開發(fā)和演示方面,但我們能做的遠不止于此。例如,你還可以使用API來瀏覽你的朋友的網(wǎng)絡,并找出你感興趣的最受歡迎的Twitter用戶。另一個吸引人的方面是對tweet消息本身進行挖掘,使用地理位置數(shù)據(jù)來了解基于位置的行為或是事件(比如說流感暴發(fā))。本文只是做了一個淺顯的介紹,請在下面隨意發(fā)表你的評論,附上你自己的各種混搭程序。Ruby和Twitter gem把為數(shù)據(jù)挖掘需要開發(fā)有用的混搭應用程序和儀表盤工具的工作變得很容易。
關于作者
M. Tim Jones是一位嵌入式固件架構師,也是Artificial Intelligence: A Systems Approach, GNU/Linux Application Programming (現(xiàn)在是第二版)、AI Application Programming (第二版)和BSD Sockets Programming from a Multilanguage Perspective等書的作者。他的工程背景涉及廣泛,從同步宇宙飛船的內(nèi)核開發(fā)到嵌入式系統(tǒng)架構和網(wǎng)絡協(xié)議開發(fā)都有。Tim是Intel的一位平臺架構師,也是一位作家,居住在科羅拉多州的 Longmont。
原文:http://select.yeeyan.org/view/213582/223628
【編輯推薦】