ããã°æ°è¨ã®ãç¥ãã
Livedoor Blogã§ããã°æ°ããéè¨ãã¦ã¿ã¾ããã
僕はただ僕らしく
ã¨ã¯è¨ã£ã¦ãããã®ããã°ãè¾ããã¤ããã§ã¯ãªããæè¡ã¨é¢ä¿ãªãæ¯è¨ãæ¸ãå ´æã欲ããã¨æã£ãã ãã§ãã
ãã¨ã¯JavaScriptå®è¡ã§ããããã°æ¬²ãããªã¨æã£ãã®ãããã¾ããã
æè¡ç³»ã®ãã¨(ã°ãªã¢ã³ä½ã£ããã¨ã)ã«é¢ãã¦ã¯ãä»å¾ããã£ã¡ã§ãæ¸ãäºå®ã§ãã
ããã¦ãã³ã©ã ãããªãããå±äººæ§ã®é«ããã®ã¯ãã£ã¡ã§æ¸ãããã«ãããã¨æã£ã¦ã¾ãã
èå³ã®ããæ¹ã¯è¦ã«æ¥ã¦ãã£ã¦ãã ãããããã¦ããã¡ããä»å¾ã¨ããããããé¡ããã¾ãã
Twitterã®ãã©ãã¯ã¼ä¸è¦§ã®ãã¼ã¸ã§ãããã£ã¼ã«æ å ±ã表示ããããã¯ãã¼ã¯ã¬ããæ¸ãããã
ãä¹
ãã¶ãã§ãã
æ´æ°ãã ãã¶æ ã£ã¦ãããã§ããã©ãã¡ãã£ã¨æ¸ãã¦ã¿ãããã¯ãã¼ã¯ã¬ããã®ç´¹ä»ããã¨ãã¾ãã
å 容
ãã©ãã¼ãã¦ã人(following)ã¨ãããã¦ã人(followers)ã®ä¸è¦§ãã¼ã¸ã§
ããããã®ææ°ã®ãã¹ããä¸åã ã表示ããã¦ã¾ããã©ã
å人çã«ã¯ããããããã®äººã®ãããã£ã¼ã«ãè¦ããã¨æã£ã¦ä»¥ä¸ã®ãããªããã¯ãã¼ã¯ã¬ããæ¸ãã¦ã¿ã¾ããã
ã¨ã£ãã«èª°ãä½ã£ã¦ãããªæ°ããã¾ãããç¿ä½ã£ã¦ãã¨ã§ã
使ãæ¹
Twitterã®ãã©ãã¯ã¼ä¸è¦§ãã¼ã¸(ä¾ï¼http:twitter.com/ombran/followers)ã§
ãã©ã¦ã¶ã®ã¢ãã¬ã¹ãã¼ã«è²¼ãä»ãã¦å®è¡ãã¦ã¿ã¦ãã ããã
Firefox3.5.5ã¨Opera10.01ã§åä½ç¢ºèªãã¦ã¾ããä»ã®ãã©ã¦ã¶ã§ããã¶ãåãã¯ãã
[注æç¹]表示ããã¦ãã¦ã¼ã¶(20å)åã®éä¿¡ãè¡ãããã®ã§ãå¦çãéããªãå¯è½æ§ãããã¾ãã
ãããã£ã¼ã«æ å ±è¿½å çããã¯ãã¼ã¯ã¬ãã
ã¦ã¼ã¶ããããã®ææ°ãã¹ãã®ä¸ã«ãããã£ã¼ã«æ å ±ã追å ããã¾ãã
javascript:(function(){var addresses = $("#follow_grid address"); addresses.each(function(){ var user = $(this).find(".screenname:first > a").text(); var user_url = "http://twitter.com/" + user; var self = this; $.get(user_url, {}, function(response){ bio = $(response).find("#bio > .bio").text(); $(self).append("<br /><span>" + bio + "</span>"); }); }); })();
ãããã£ã¼ã«æ å ±æ¸æçããã¯ãã¼ã¯ã¬ãã
ã¦ã¼ã¶ããããã®ææ°ãã¹ãããããã£ã¼ã«æ å ±ã«æ¸ãæãã¾ãã
javascript:(function(){ var addresses = $("#follow_grid address"); addresses.each(function(){ var user = $(this).find(".screenname:first > a").text(); var user_url = "http://twitter.com/" + user; var self = this; $.get(user_url, {}, function(response){ bio = $(response).find("#bio > .bio").text(); $(self.parentNode).find(".user-body:first .currently").replaceWith("<span>" + bio + "</span>"); }); }); })();
ã½ã¼ã¹
æ¬å½ã¯ã°ãªã¢ã³ã«ããäºå®ã ã£ããã§ãããjQueryã®é¢ä¿ã§ãã¾ãåä½ããªãã£ããã§ã
ã¨ããããããã¯ãã¼ã¯ã¬ããã§å
¬éãã¾ããã
ããããã¯ä»¥ä¸ã®ã½ã¼ã¹ãäºã¤ã«åãããã®ã§ãã
(function(){ // ãããã£ã¼ã«æ å ±ã®è¿½è¨ãæ¸æãã®ãã©ã° // true: æ¸æ, false: è¿½è¨ var replace = false; var addresses = $("#follow_grid address"); addresses.each(function(){ // ã¦ã¼ã¶ååå¾ var user = $(this).find(".screenname:first > a").text(); var user_url = "http://twitter.com/" + user; // ãããã£ã¼ã«è¿½å var self = this; $.get(user_url, {}, function(response){ // ã¦ã¼ã¶ãã¼ã¸ãããããã£ã¼ã«æ å ±åå¾ bio = $(response).find("#bio > .bio").text(); if(replace){ // 表示å 容ããããã£ã¼ã«æ å ±ã«æ¸æ $(self.parentNode).find(".user-body:first .currently").replaceWith("<span>" + bio + "</span>"); } else { // 表示å 容ã«ãããã£ã¼ã«æ å ±ã追å $(self).append("<br /><span>" + bio + "</span>"); } }); }); })();
Twitterã®ãã¼ã¸å ã§ã¤ã³ã¯ãªã¡ã³ã¿ã«ãµã¼ãããã°ãªã¢ã³æ¸ããã
[2009å¹´2æ23æ¥è¿½è¨]
Twitterã®ãã¼ã¸å
ãã¤ã³ã¯ãªã¡ã³ã¿ã«ãµã¼ãããã°ãªã¢ã³ä½ãã¾ããã
ã¡ã¢ç¨ã«ãµãã¼ã£ã¦ããã¤ã¨ããæ¢ããããããç¨éã¨ãã«ä½¿ããããªã
ååã¯é©å½ã«ãtwincreãã»ã»ã»ã»ã³ã¹ãããã¾ãããw
ååã¯ãTwitter Incremental Search Helperãã«å¤ãã¾ãããé·ãã§ããã©ããããããã¨ãããã¨ã§ã
ãã¼ã¸å
ã«ãã¼ã¿ãå¤ããã°å¤ãã»ã©ä¾¿å©ããä¸ãããã§ãAutoPagerizeã¨ä½µç¨ãæ¨å¥¨ãã¾ãã
ã¨ããããã1ãã¼ã¸ã«è¡¨ç¤ºãããéãªãæ®éã«è¦ãã»ããæ©ãã§ããw
å®éã«ã¤ã³ã¹ãã¼ã«ããã¨ä¸ã®ãããªã¤ã³ã¯ãªã¡ã³ã¿ã«ãµã¼ãç¨ã®ããã¹ãå
¥åããã¯ã¹ã表示ãããã®ã§ã
ããã«æ¤ç´¢ãã¼ã¿ã®å
¥åãè¡ãã°ã対å¿ãããã¼ã¿ã®ã¿è¡¨ç¤ºãããããã«ãªãã¾ãã
ãã¨ãdocument.getElementsByClassNameã¨ããé¢æ°ãã¤ãã£ã¦ãã®ã§ãFirefox2ã§ã¯åãã¾ããã
ã¨ããããã§ãFirefox3å°ç¨ã¨ãªãã¾ããOperaã ã¨9.50以ä¸ãªãåãããã
githubã«ç½®ãã¦ããã®ã§ã使ãããããã¯ãèªç±ã«ã©ããã
twitter_incremental_search_helper.user.js · GitHub
Userscripts.orgã«ãç½®ãããã«ãã¾ããã
http://userscripts.org/scripts/show/42933
HTMLã¬ã³ããªã³ã°ã¨ã³ã¸ã³ã¨JavaScriptã¨ã³ã¸ã³ã®å¯¾å¿ã«ã¤ãã¦èª¿ã¹ã¦ã¿ã
ã¡ãã£ã¨HTMLã¬ã³ããªã³ã°ã¨ã³ã¸ã³ã¨JavaScriptã¨ã³ã¸ã³ã®å¯¾å¿ã«ã¤ãã¦èª¿ã¹ãããããã§ããã®ã¡ã¢ã
åå調ã¹ãã ããªãã§ã詳ãããã¨ã¯ã°ã°ã£ã¦ãã ããã
HTMLã¬ã³ããªã³ã°ã¨ã³ã¸ã³ | JavaScriptã¨ã³ã¸ã³ | 主ãªWebãã©ã¦ã¶ |
---|---|---|
Gecko | SpiderMonkey | Firefox 3.0ã¾ã§ |
TraceMonkey | Firefox 3.1以éã«å®è£ äºå® | |
WebKit | JavaScriptCore | Safari |
V8 | Google Chrome | |
Presto | linear_b | Opera 7ãã9.27ã¾ã§ |
futhark | Opera 9.50以é | |
Trident | JScript | Internet Explorer |
[ä¿®æ£]SquirrelFish Extremeã¯JavaScriptCoreã®ä¸é¨(VMã®å称)
以ä¸
ãããªæãã§ããããééããã£ããæãã¦ãã ããã
gihyo.jpã®ãå ·ä½ä¾ã§å¦ã¶ï¼æ å ±å¯è¦åã®ãã¯ããã¯ãã®ããã°ã©ã ãåæã«Rubyã§æ¸ãæãã¦ã¿ãããã®ï¼
åæã«Rubyã§æ¸ãæãã¦ã¿ãããã°ã©ã ãä»åã§ã©ã¹ãã«ãªãã¾ãã
ããã°ã©ã ã®ãã¦ã³ãã¼ãã¯ä»¥ä¸ã®ãªã³ã¯å
ã®downloadãããèªç±ã«ã©ããã
GitHub - ombran/gihyojp-visualization-ruby: The Ruby version of the information visualization introduced by gihyo.jp.(unofficial)
ä»åã¯visualization6ãã©ã«ãã®ããã°ã©ã ã«ã¤ãã¦ã®èª¬æã«ãªãã¾ãã
visualization6ã®èª¬æ
å
è¨äºã ã¨第6回ã«ãããå
容ã«ãªãã¾ãã
ãã®ããã°ã©ã ã¯ãã¯ã¦ãªããã¯ãã¼ã¯ã®äººæ°ã¨ã³ããªã¼ãããªã¼ãããã¨ãã¦å¯è¦åããããã°ã©ã ã«ãªãã¾ãã
詳ãããã¨ã¯å
è¨äºãè¦ã¦ããã£ãã»ããããããããã¨æãã¾ãã
visualization6ãã©ã«ãã®å 容
visualization6ã®ãã©ã«ãå 容ã¯ä»¥ä¸ã®ããã«ãªã£ã¦ãã¾ãã
$ tree visualization6 visualization6
-- Demo.rb | |
-- Visualization | |
-- BinaryTreeMapRenderer.rb | |
-- Bookmark.rb | |
-- BookmarkDetail.rb | |
-- BookmarkItem.rb | |
-- Cluster.rb | |
-- ClusterBuilder.rb | |
-- DistanceEvaluator.rb | |
-- HatenaBookmarkAPI.rb | |
-- Item.rb | |
-- MultiVector.rb | |
-- Node.rb | |
-- TreeMapRenderer.rb | |
`-- WardDistanceEvaluator.rb | |
-- Visualization.rb |
Visualization.rbãèªã¿è¾¼ããã¨ã ãã§ãVisualizationãã©ã«ã以ä¸ã®ãã¡ã¤ã«ãå
¨ã¦èªã¿è¾¼ããããã«ãã¦ããã¾ãã
Demo.rbããã¢ç¨ã®ããã°ã©ã ã¨ãªãã¾ãã
RMagickã¨JSONã©ã¤ãã©ãªã®ã¤ã³ã¹ãã¼ã«
ç»åå¦çã«RMagickãJSONãã¼ã¿ã®ãã¼ã¹ã«JSONã©ã¤ãã©ãªã使ç¨ããã®ã§ããããããã¤ã³ã¹ãã¼ã«ãã¦ããã¦ãã ããã
ã¾ãRMagickã¯gemã ã¨
# gem install rmagick
ã¡ãªã¿ã«ãUbuntuã ã¨aptã§ã¤ã³ã¹ãã¼ã«ã§ãã¾ãã
# apt-get install librmagick-ruby
次ã«JSONã©ã¤ãã©ãªã¯gemã§ã¤ã³ã¹ãã¼ã«ã§ãã¾ãã
# gem install json
ããã°ã©ã ã®èª¬æ
åºæ¬çã«ããã°ã©ã ã®ã¯ã©ã¹ããããã¯å
è¨äºã®ããã°ã©ã ã¨å¯¾å¿ããã¦ããã®ã§ãè¦æ¯ã¹ãããããã«ãã¦ããã¾ãã
ãã ãããã¯ãã¼ã¯ã®ã¿ã°ãæ´æ°ã¤ã³ããã¯ã¹ã«å¤æããIndexMapperã¯ã©ã¹ã¨ããã®ãå
è¨äºã®ããã°ã©ã ã«ã¯ããã¾ããããã¡ãã®ããã°ã©ã ã§ã¯MultiVectorã¯ã©ã¹ã®ãã¼ã¿ãããã·ã¥ã§ä½æãã¦ããã®ã§ãIndexMapperã¯ã©ã¹ããããªããªãã¾ãã
以ä¸ã®BookmarkItemã¯ã©ã¹ããå
è¨äºã§ã®ãããã³ã°ããã¦ããªããã¨ããããã¨æãã¾ãã
# BookmarkItem.rb module Visualization # ã¯ã¦ãªããã¯ãã¼ã¯ã¨ã³ããªã«å¯¾å¿ããæ«ç«¯ãã¼ã class BookmarkItem < Visualization::Item # @param bookmarkï¼Visualization::Bookmarkãªãã¸ã§ã¯ã # @param detailï¼Visualization::BookmarkDetailãªãã¸ã§ã¯ã def initialize(bookmark, detail) # ããã¯ãã¼ã¯æ°ããã®ã¾ã¾å¹³ååããã¨æ¯çã極端ã«ãªãã®ã§ # å¹³æ¹æ ¹ãã¨ã£ã¦èª¿æ´ãã super(bookmark.title, tagsToVector(detail), Math.sqrt(detail.bookmarkCount)) @bookmark = bookmark @detail = detail end def tagsToVector(detail) vector = Visualization::MultiVector.new detail.tags.each do |tag| vector.set(tag => (vector.get(tag).to_i + 1)) end vector.normalize return vector end def getBookmark return @bookmark end def getDetail return @detail end end end
ãã¨ã¯ãç»åæç»ããã¦ããBinaryTreeMapRendererã¯ã©ã¹ã§ããã
åºæ¬çã«å
è¨äºã¨åãã§ãããç»åã«æåãæ¸ãè¾¼ãã§ããdrawStringWithinã¡ã½ããã¯ç¹æ®ãªãã§èª¬æãã¨ãã¾ãã
ã¾ãããã°ã©ã ã¯ä»¥ä¸ã®ããã«ãªãã¾ãã
# BinaryTreeMapRenderer.rbï¼ä¸é¨åï¼ module Visualization class BinaryTreeMapRenderer ... # ããã¯ãã¼ã¯ãããã¨ã³ããªã®ã¿ã¤ãã« def drawStringWithin(draw, title, rect) d = draw # ãã©ã³ããµã¤ãº pointsize = [(Math.sqrt(rect.width * rect.height) / 10).to_i, 10].max # æ¥æ¬èªè¡¨ç¤ºã®ããã«ãã©ã³ãæå®(ç°å¢ã«ãã£ã¦å¤æ´ãã¦ãã ãã) d.font = "/usr/share/fonts/truetype/kochi/kochi-gothic.ttf" # æåè² d.fill("white") d.stroke_width(0) d.pointsize(pointsize) # æåãæ¹è¡ããªããåºå words = [rect.width.to_f/pointsize.to_f, 1].max.to_i t_ary = title.split("") t_size = t_ary.size rows = (t_size.to_f/words.to_f).ceil rows.times do |i| start = i * words finish = ((i + 1) * words) - 1 text = t_ary[start..finish].join y = rect.y + pointsize * (i + 1) d.text(rect.x + 5, y + 5, text) end end end end
d.fontã§ãã©ã³ãã®æå®ãããªãã¨æ¥æ¬èªã表示ã§ããªãã®ã§æ°ãã¤ãã¦ãã ãããã¾ãããã¯ç°å¢ã«ãã£ã¦éãã®ã§ãããããã®ç°å¢ã§æ¥æ¬èªã表示ã§ãããã©ã³ãã®çµ¶å¯¾ãã¹ãæå®ãã¦ãã ããã
ãã¨ã¯pointsizeã§æåã®å¤§ãããè¨å®ãã¦ãããã表示é åãã¨ã«æååãæ¹è¡ããªãã表示ãã¦ãã¾ãã
ã¡ãªã¿ã«ããã¯ãã¼ã¯æ°ãå¤ãã§æåã®å¤§ãããå¤æ´ãã¦ããã¾ãã
ãã¢ããã°ã©ã ã®å®è¡
ããã°ã©ã ã®ãã¢ãè¡ãDemoã¯ã©ã¹ã¯ä»¥ä¸ã®ããã«ãªãã¾ãã
# Demo.rb $KCODE = 'u' require 'rubygems' require 'RMagick' require File.dirname(__FILE__) + '/Visualization' class Demo include Visualization # åºåãã¡ã¤ã«å OUTPUT_FILE_NAME = 'hatena_bookmark.png' def run api = HatenaBookmarkAPI.new bookmarks = api.getHotEntries puts bookmarks.size.to_s + " entries." # é層çã¯ã©ã¹ã¿ãªã³ã°ã®å ¥åãã¼ã¿ãä½æ input = [] bookmarks.each do |bookmark| puts bookmark.title puts " [url] " + bookmark.url # ãµã¼ãã®è² è·ãæããããå¼ã³åºãééã空ãã sleep(1) detail = api.getDetail(bookmark.url) input << BookmarkItem.new(bookmark, detail) if (detail != nil) puts " [bookmarkCount] " + detail.bookmarkCount.to_s puts " [tags] [" + detail.tags.join(", ") + "]" end end # Wardæ³ã«åºã¥ãé層çã¯ã©ã¹ã¿ãªã³ã°ãæºå evaluator = Visualization::WardDistanceEvaluator.new builder = Visualization::ClusterBuilder.new(evaluator) # ã¯ã©ã¹ã¿ãªã³ã°ãå®è¡ puts "ã¯ã©ã¹ã¿ãªã³ã°éå§(çµæ§æéãããã¾ã)" result = builder.build(input) puts "ã¯ã©ã¹ã¿ãªã³ã°çµäº" # ã¯ã©ã¹ã¿ãªã³ã°çµæã表示 puts "ç»åçæéå§" output(result) puts "åºåãã¡ã¤ã«ï¼" + OUTPUT_FILE_NAME end def output(node) # åºåç»åãä½æ g = Magick::Image.new(1024, 768) # ã°ã©ãã£ãã¯ãªãã¸ã§ã¯ããä½æ d = Magick::Draw.new # èæ¯ãç½ã§å¡ãã¤ã¶ã d.fill("white") d.rectangle(0, 0, g.columns, g.rows) d.draw(g) # ããªã¼ãããã®æç»ãå®è¡ renderer = Visualization::BinaryTreeMapRenderer.new bounds = Magick::Rectangle.new(g.columns - 40, g.rows - 40, 20, 20) renderer.render(g, node, bounds) # ç»åãPNGãã¡ã¤ã«ã«ä¿å g.write(OUTPUT_FILE_NAME) end end demo = Demo.new demo.run
ãã¢ããã°ã©ã ãå®è¡ããã¨ã以ä¸ã®ãããªåºåãå¾ããã¾ãã
$ ruby Demo.rb 30 entries. ããããã¹ã¼ãã®ã¬ã·ãé:ã¢ã«ãã¡ã«ãã¡ã¢ã¶ã¤ã¯ [url] http://alfalfa.livedoor.biz/archives/51402336.html [bookmarkCount] 249 [tags] [ãã¨ã§èªã, ã¬ã·ã, ãå½¹ç«ã¡, ... ... ã¯ã©ã¹ã¿ãªã³ã°éå§(çµæ§æéãããã¾ã) 30 29 28 27 26 ... 6 5 4 3 2 ã¯ã©ã¹ã¿ãªã³ã°çµäº ç»åçæéå§ åºåãã¡ã¤ã«ï¼hatena_bookmark.png
ããã§ãhatena_bookmark.pngã¨ãã以ä¸ã®ãããªç»åãã¡ã¤ã«ãåºåããã¾ãã
ããªã¼ãããã«ãã£ã¦ã¯ã©ã¹ã¿ãªã³ã°ã®çµæãè¦è¦çã«ãããããã表ç¾ããã¦ãããã¨ããããã¨æãã¾ãã
ãã ããå
¥åãã¼ã¿ã¯ãã¯ã¦ãªããã¯ãã¼ã¯ã®ãããã³ããªã«ä¾åããã®ã§ãåºåãããç»åã¯ãã®æã«ãã£ã¦å¤åãã¾ãã
以ä¸
ä»åã§ãã¯ã¦ãªããã¯ãã¼ã¯ã®ãããã³ããªã®ããªã¼ãããåãã§ããããã«ãªã£ãã®ã§ãããã§åæã«Rubyã§æ¸ãæããããã°ã©ã ã¯çµäºã§ãã
æ
å ±å¯è¦åã«é¢ãã¦ãããåå¼·ã«ãªãã¾ããããã¨ãæ¸ãæããããä¸ã§Rubyã®ããã°ã©ãã³ã°ã«ã¤ãã¦ãããåå¼·ã«ãªãã¾ããã
ããããè¨äºãæ¸ãã¦ãããgihyo.jpã«æè¬ã§ãã
gihyo.jpã®ãå ·ä½ä¾ã§å¦ã¶ï¼æ å ±å¯è¦åã®ãã¯ããã¯ãã®ããã°ã©ã ãåæã«Rubyã§æ¸ãæãã¦ã¿ãããã®ï¼
前回ã前々回ã«å¼ãç¶ãã¦ä»åãåæã«Rubyã§æ¸ãæããããã°ã©ã ã®ç°¡åãªèª¬æããã¾ãã
ããã°ã©ã ã®ãã¦ã³ãã¼ãã¯ä»¥ä¸ã®ãªã³ã¯å
ã®downloadãããèªç±ã«ã©ããã
GitHub - ombran/gihyojp-visualization-ruby: The Ruby version of the information visualization introduced by gihyo.jp.(unofficial)
ä»åã¯visualization5ãã©ã«ãã®ããã°ã©ã ã«ã¤ãã¦ã®èª¬æã«ãªãã¾ãã
visualization5ã®èª¬æ
å
è¨äºã ã¨第5回ã«ãããå
容ã«ãªãã¾ãã
ãã®ããã°ã©ã ã¯ãã¯ã¦ãªããã¯ãã¼ã¯ãæä¾ããWeb APIã«ã¢ã¯ã»ã¹ãï¼äººæ°ã¨ã³ããªã¼ã®æ
å ±ãåå¾ããããã°ã©ã ã«ãªãã¾ãã
詳ãããã¨ã¯å
è¨äºãè¦ã¦ããã£ãã»ããããããããã¨æãã¾ãã
visualization5ãã©ã«ãã®å 容
visualization5ã®ãã©ã«ãå 容ã¯ä»¥ä¸ã®ããã«ãªã£ã¦ãã¾ãã
visualization5
-- Demo.rb | |
-- Visualization | |
-- Bookmark.rb | |
-- BookmarkDetail.rb | |
`-- HatenaBookmarkAPI.rb |
å
è¨äºã®ããã°ã©ã ã¨æ¡å¼µåã®éãã¯ããã¾ããããã¡ã¤ã«åã¨å
容ã対å¿ããã¦ããã¾ãã
Visualization.rbãèªã¿è¾¼ããã¨ã ãã§ãVisualizationãã©ã«ã以ä¸ã®ãã¡ã¤ã«ãå
¨ã¦èªã¿è¾¼ããããã«ãã¦ããã¾ãã
Demo.rbããã¢ç¨ã®ããã°ã©ã ã¨ãªãã¾ãã
JSONã©ã¤ãã©ãªã®ã¤ã³ã¹ãã¼ã«
ä»åã¯JSONå½¢å¼ã®ãã¼ã¿ãæ±ãã®ã§ãJSONã©ã¤ãã©ãªãã¤ã³ã¹ãã¼ã«ãã¦ããã¾ãã
gemãç¨ãã¦ä»¥ä¸ã®ããã«ã¤ã³ã¹ãã¼ã«ã§ãã¾ãã
# gem install json
ããã°ã©ã ã®èª¬æ
ã¾ããã¼ã¿æ ¼ç´ç¨ã®ã¯ã©ã¹ã§ãããBookmarkã¯ã©ã¹ã¯ã¨ã³ããªæ å ±ãæ ¼ç´ããã¯ã©ã¹ã§ãBookmarkDetailã¯ã©ã¹ã¯ããã¯ãã¼ã¯æ°ãã¿ã°ã®ä¸è¦§ãªã©ã¨ã³ããªã®è©³ç´°ãæ ¼ç´ããã¯ã©ã¹ã¨ãªã£ã¦ãã¾ãã
次ã«ãä»åã®ã¡ã¤ã³ã¨ãªãHatenaBookmarkAPIã¯ã©ã¹ã«ã¤ãã¦èª¬æãã¾ãã
ããã°ã©ã ã¯ä»¥ä¸ã®ããã«ãªãã¾ãã
# HatenaBookmarkAPI.rb require 'rss' require 'open-uri' require 'uri' require 'rubygems' require 'json' module Visualization # ã¯ã¦ãªããã¯ãã¼ã¯ã®APIã«ã¢ã¯ã»ã¹ããã¯ã©ã¹ class HatenaBookmarkAPI # 人æ°ã¨ã³ããªã¼ã®æ å ±ãåå¾ # @returnï¼ããã¯ãã¼ã¯æ å ±ã®ãªã¹ã def getHotEntries bookmarks = [] content = nil # 人æ°RSSãã£ã¼ããèªã¿è¾¼ã open("http://b.hatena.ne.jp/hotentry.rss"){|u| content = u.read } rss = nil # RSSãParseãã begin rss = RSS::Parser::parse(content) rescue RSS::InvalidRSSError rss = RSS::Parser::parse(content, false) end # åã¨ã³ããªã®æ å ±ãåå¾ rss.items.each do |item| bookmark = Visualization::Bookmark.new bookmark.url = item.link bookmark.title = item.title bookmarks << bookmark end return bookmarks end # ããã¯ãã¼ã¯ã®è©³ç´°æ å ±ãåå¾ # @param urlï¼ããã¯ãã¼ã¯å¯¾è±¡ã®URL # @returnï¼è©³ç´°æ å ± def getDetail(url) encodeUrl = URI.encode(url) # ã¨ã³ããªæ å ±åå¾APIã®URL apiUrl = "http://b.hatena.ne.jp/entry/json/?url=" + encodeUrl json = nil # URLãéãããã¼ã¿ãèªã¿è¾¼ã open(apiUrl) do |f| # JSONããã¼ã¹ if f.read =~ /^\((.*)\)$/ json = JSON.parse($1) end end # 詳細æ å ±ãä½æ detail = Visualization::BookmarkDetail.new detail.bookmarkCount = json["count"].to_i detail.tags = [] # bookmarksé åãèªã¿è¾¼ã bookmarks = json["bookmarks"] bookmarks.each do |item| # tagsé åãèªã¿è¾¼ã tags = item["tags"] tags.each do |tag| detail.tags << tag end end return detail end end end
getHotEntriesã¡ã½ããã¯ãã¯ã¦ãªããã¯ãã¼ã¯ã®äººæ°ã¨ã³ããªã®ä¸è¦§ãVisualization::Bookmarkãªãã¸ã§ã¯ãã®é
åã¨ãã¦è¿ãã¡ã½ããã§ãã
RSSãã£ã¼ããåå¾ããããã«open-uriã©ã¤ãã©ãªããRSSãã£ã¼ãããã¼ã¹ããããã«RSSã©ã¤ãã©ãªã使ç¨ãã¦ãã¾ãã
getDetailã¡ã½ããã¯ãç¹å®ã®URLããããã¯ãã¼ã¯ã¨ã³ããªã®è©³ç´°æ
å ±ãåå¾ããã¡ã½ããã§ãã
JSONãã¼ã¿ã®ãã¼ã¹ã®ããã«JSONã©ã¤ãã©ãªã使ç¨ãã¦ãã¾ãã
ã¡ãªã¿ã«ãJSONã®ãã¼ã¹ã®éã«
# JSONããã¼ã¹ if f.read =~ /^\((.*)\)$/ json = JSON.parse($1) end
ã¨ãã¦ãåå¾ããã¯ã¦ãªããã¯ãã¼ã¯ã®JSONãã¼ã¿ã®æåã¨æå¾ã«ããæ¬å¼§ãåãé¤ãã¦ãããªãã¨ãã¼ã¹ã®éã«ã¨ã©ã¼ã«ãªã£ã¦ãã¾ãã®ã§æ°ãä»ãã¦ãã ããã
ãã¢ããã°ã©ã ã®å®è¡
ããã°ã©ã ã®ãã¢ãè¡ãDemoã¯ã©ã¹ã¯ä»¥ä¸ã®ããã«ãªãã¾ãã
# Demo.rb require File.dirname(__FILE__) + '/Visualization' class Demo include Visualization def run api = HatenaBookmarkAPI.new bookmarks = api.getHotEntries puts bookmarks.size.to_s + " entries." bookmarks.each do |bookmark| puts bookmark.title puts " [url] " + bookmark.url # ãµã¼ãã®è² è·ãæããããå¼ã³åºãééã空ãã sleep(1) detail = api.getDetail(bookmark.url) if (detail != nil) puts " [bookmarkCount] " + detail.bookmarkCount.to_s puts " [tags] [" + detail.tags.join(", ") + "]" end end end end demo = Demo.new demo.run
Demoã¯ã©ã¹ãå®è¡ããã¨ï¼å®è¡æç¹ã§ã®ææ°ã®äººæ°ã¨ã³ããªã¼ã®æ å ±ãï¼ä¾ãã°æ¬¡ã®ããã«åºåããã¾ãã
$ ruby Demo.rb 30 entries. ãã¢é æ¥æ¬SUGEEEEEEEEEEEEEEEE!ã£ã¦ãªãã³ãããã [url] http://vipvipblogblog.blog119.fc2.com/blog-entry-248.html [bookmarkCount] 373 [tags] [2ch, neta, ãã¿, 2ch, ãã¨ã§èªã, ... SEOãSMMã®ããã«ããã°ãä½ã£ããã¾ããããã¨ãªã¹ã - ã½ã¼ã·ã£ã«ã¡ãã£ã¢ãã¼ã±ãã£ã³ã°(SMM).jp [url] http://www.socialmediamarketing.jp/2008/12/seosmm.html [bookmarkCount] 265 [tags] [SEO, Webãµã¼ãã¹, seo, webå¶ä½, ã¾ã¨ã, ... Color of Book - éèªã®è²ããhtml,cssã§å©ç¨ã§ããã«ã©ã¼ãã£ã¼ãã®ç´¹ä» [url] http://colorchart.jp/ [bookmarkCount] 362 [tags] [color, webãã¶ã¤ã³, webãµã¼ãã¹, css, ... ...
ã¨ã³ããªã®urlãããã¯ãã¼ã¯æ°ãã¿ã°ã®ä¸è¦§ã表示ããã¦ãã®ããããã¨æãã¾ãã
以ä¸
ä»åã¯ããã¾ã§ãã
ç´°ããé¨åã¯ããã°ã©ã ãå
è¨äºãè¦ã¦ãã ããã
ãã¨ãééã£ã¦ãé¨åãªã©ããã¾ãããæãã¦ãã ããã
次åã®å¯è¦åã§æå¾ã«ãªãã¾ãã
gihyo.jpã®ãå ·ä½ä¾ã§å¦ã¶ï¼æ å ±å¯è¦åã®ãã¯ããã¯ãã®ããã°ã©ã ãåæã«Rubyã§æ¸ãæãã¦ã¿ãããã®ï¼
前回ã«å¼ãç¶ããä»åãåæã«Rubyã§æ¸ãæããããã°ã©ã ã®ç°¡åãªèª¬æããã¾ãã
ããã°ã©ã ã®ãã¦ã³ãã¼ãã¯ä»¥ä¸ã®ãªã³ã¯å
ã®downloadãããèªç±ã«ã©ããã
GitHub - ombran/gihyojp-visualization-ruby: The Ruby version of the information visualization introduced by gihyo.jp.(unofficial)
ä»åã¯visualization4ã®ãã©ã«ãã«ããããã°ã©ã ã®èª¬æãã¾ãã
visualization4ã®èª¬æ
å
è¨äºã ã¨第3回ã第4回ã«ãããå
容ã«ãªãã¾ãã
ãã®ããã°ã©ã ã¯é層çã¯ã©ã¹ã¿ãªã³ã°ã®å®è¡çµæãããªã¼ãããã§è¡¨ç¾ãããã®ã§ãã
詳ãããã¨ã¯å
è¨äºãè¦ã¦ããã£ãã»ããããããããã¨æãã¾ãã
visualization4ãã©ã«ãã®å 容
visualization4ã®ãã©ã«ãå 容ã¯ä»¥ä¸ã®ããã«ãªã£ã¦ãã¾ãã
$ tree visualization4/ visualization4/
-- Demo.rb | |
-- Visualization | |
-- BinaryTreeMapRenderer.rb | |
-- Cluster.rb | |
-- ClusterBuilder.rb | |
-- ColorItem.rb | |
-- DistanceEvaluator.rb | |
-- Item.rb | |
-- MultiVector.rb | |
-- Node.rb | |
-- TreeMapRenderer.rb | |
`-- WardDistanceEvaluator.rb | |
-- Visualization.rb |
ä»åãåååæ§ãå
è¨äºã®ããã°ã©ã ã¨æ¡å¼µåã®éãã¯ããã¾ããããã¡ã¤ã«åã¨å
容ã対å¿ããã¦ããã¾ãã
Visualization.rbãèªã¿è¾¼ããã¨ã ãã§ãVisualizationãã©ã«ã以ä¸ã®ãã¡ã¤ã«ãå
¨ã¦èªã¿è¾¼ããããã«ãã¦ããã¾ãã
Demo.rbããã¢ç¨ã®ããã°ã©ã ã§ãtreemap.pngã¯åºåçµæã¨ãªãã¾ãã
RMagickã®ã¤ã³ã¹ãã¼ã«
ããã°ã©ã ã®èª¬æã®åã«ãRMagickã®ã¤ã³ã¹ãã¼ã«æ¹æ³ã«ã¤ãã¦èª¬æãã¾ãã
ä»åã®ããã°ã©ã ã§ã¯ç»åãæ±ãã®ã§ãç»åå¦çç¨ã®ã©ã¤ãã©ãªã¨ãã¦RMagickãç¨ããããã§ãã
gemã ã¨ä»¥ä¸ã®ããã«ãªãã¾ãã
# gem install rmagick
RMagickã®ã¤ã³ã¹ãã¼ã«ã«ã¯ã©ã¤ãã©ãªãè²ã
å¿
è¦ã«ãªãã¾ããã©ã
ããã¯ããããªã¨ããã§æ¸ããã¦ãã¨æãã®ã§é å¼µã£ã¦ãã ããã
ã¡ãªã¿ã«ãUbuntuã¨ããªããaptã§ç°¡åã«ã¤ã³ã¹ãã¼ã«ã§ãã¾ãã
# apt-get install librmagick-ruby
ããã°ã©ã ã®èª¬æ
ä»åã®ããã°ã©ã ã§å
è¨äºã®ããã°ã©ã ã¨å¤§ããªéãã¯ãç»åæç»é¨åã«ãªãã¾ãã
ãããã使ã£ã¦ãã©ã¤ãã©ãªéããã§ãå½ç¶ã¨ããã°å½ç¶ã§ããã
ãã®ç»åæç»ã®ããã°ã©ã ã¯BinaryTreeMapRenderer.rbã§ã以ä¸ã®ããã«ãªãã¾ãã
# BinaryTreeMapRenderer.rb require 'rubygems' require 'RMagick' module Visualization # # é åã®2åå²ãå帰çã«ç¹°ãè¿ããããªã¼ãããã®æç»ãè¡ã # class BinaryTreeMapRenderer include Visualization::TreeMapRenderer def render(graphic, node, bounds) doRender(graphic, node, bounds, 0) end def doRender(graphic, node, bounds, depth) d = Magick::Draw.new if (node.kind_of? Visualization::ColorItem) # ãã¼ããè²é ç®ã®å ´åã¯ããã®è²ã§é·æ¹å½¢ãå¡ãã¤ã¶ã d.fill("rgb(#{node.getVector.data[:red]}, #{node.getVector.data[:green]}, #{node.getVector.data[:blue]}, #{depth})") d.rectangle(bounds.x, bounds.y, bounds.x + bounds.width, bounds.y + bounds.height) elsif (node.kind_of? Visualization::Cluster) cluster = node # åãã¼ãchild1ã¨child2ãåå¾ child1 = cluster.getLeft child2 = cluster.getRight # child1ã®é¢ç©ã®æ¹ã大ãããªãããã«ãã if (child1.getArea < child2.getArea) temp = child1 child1 = child2 child2 = temp end # åãã¼ãã®é¢ç©æ¯ãè¨ç® area1 = child1.getArea area2 = child2.getArea ratio1 = area1 / (area1 + area2) ratio2 = area2 / (area1 + area2) x = bounds.x y = bounds.y w = bounds.width h = bounds.height rect1 = nil rect2 = nil # é ååå²ãå®è¡ if (w > h) # boundsã横é·ã®å ´åãå·¦å³ã«åå² rect1 = Magick::Rectangle.new(ratio1 * w, h, x, y) rect2 = Magick::Rectangle.new(ratio2 * w, h, x + ratio1 * w, y) else # boundsã縦é·ã®å ´åãä¸ä¸ã«åå² rect1 = Magick::Rectangle.new(w, ratio1 * h, x, y) rect2 = Magick::Rectangle.new(w, ratio2 * h, x, y + ratio1 * h) end # åãã¼ããå帰çã«å¦çãã doRender(graphic, child1, rect1, depth + 1) doRender(graphic, child2, rect2, depth + 1) end # 輪éãé層ã®æ·±ãã«å¿ãã太ãã§æç» d.fill("transparent") borderWidth = [8 - depth, 1].max d.stroke_width(borderWidth) d.stroke("black") d.rectangle(bounds.x, bounds.y, bounds.x + bounds.width, bounds.y + bounds.height) d.draw(graphic) end end end
doRenderã¡ã½ããã®graphicã¯Magick::Imageãªãã¸ã§ã¯ããboundsã¯Magick::Rectangleãªãã¸ã§ã¯ãã«ãªãã¾ãã
d.fillã§å¡ãã¤ã¶ãã®è²ãè¨å®ããd.rectangleã§åè§ã®æç»ãè¡ãã¾ãã
ãã¨d.stroke_widthã§ç·ã®å¹
æå®ãd.strokeã¨ãã§ç·ã®è²ãæå®ããããã¦ãã¾ãã
ããã¦æå¾ã«d.drawã¨ãããã¨ã§å³å½¢ã®å
ã®Magick::Imageãªãã¸ã§ã¯ãã«å³å½¢ã®æç»ãè¡ã£ã¦ãã¾ãã
RMagickã®ã¡ã½ããã®è©³ãã説æã¯こちらã«ããã®ã§ãç´°ãããã¨ã¯ãã¡ããã覧ãã ããã
ã¡ãªã¿ã«ãå
è¨äºã¨ã©ã¤ãã©ãªãªã©ã¯éãã¾ãããããã°ã©ã ã®å½¢å¼ã¯ã»ã¼åãã«ãªã£ã¦ããã®ã§ã
å
è¨äºã¨æ¯è¼ããªããè¦ããã¨æãã¾ãã
ãã¢ããã°ã©ã ã®å®è¡
ããã°ã©ã ã®ãã¢ãè¡ãDemoã¯ã©ã¹ã¯ä»¥ä¸ã®ããã«ãªãã¾ãã
# Demo.rb require 'rubygems' require 'RMagick' require File.dirname(__FILE__) + '/Visualization' class Demo include Visualization OUTPUT_FILE_NAME = 'treemap.png' def run color = Struct.new(:red, :green, :blue) # ã©ã³ãã ãªè²ãã¼ã¿ã100åä½æ input = [] 100.times do |i| c = color.new(rand(256), rand(256), rand(256)) area = 0.2 + 0.8 * rand input << ColorItem.new(c, area) end # Wardæ³ã«åºã¥ãé層çã¯ã©ã¹ã¿ãªã³ã°ãæºå evaluator = WardDistanceEvaluator.new builder = ClusterBuilder.new(evaluator) # ã¯ã©ã¹ã¿ãªã³ã°ãå®è¡ puts "ã¯ã©ã¹ã¿ãªã³ã°éå§(çµæ§æéãããã¾ã)" result = builder.build(input) puts "ã¯ã©ã¹ã¿ãªã³ã°çµäº" # ã¯ã©ã¹ã¿ãªã³ã°çµæã表示 puts "ç»åçæéå§" output(result) puts "åºåãã¡ã¤ã«ï¼" + OUTPUT_FILE_NAME end def output(node) # 400x400ãã¯ã»ã«ã®ç»åãä½æ g = Magick::Image.new(400, 400) # ã°ã©ãã£ãã¯ãªãã¸ã§ã¯ããä½æ d = Magick::Draw.new # èæ¯ãç½ã§å¡ãã¤ã¶ã d.fill("white") d.rectangle(0, 0, g.columns, g.rows) d.draw(g) # ããªã¼ãããã®æç»ãå®è¡ renderer = BinaryTreeMapRenderer.new bounds = Magick::Rectangle.new(360, 360, 20, 20) renderer.render(g, node, bounds) # ç»åãPNGãã¡ã¤ã«ã«ä¿å g.write(OUTPUT_FILE_NAME) end end demo = Demo.new demo.run
ãã¢ããã°ã©ã ãå®è¡ããã¨ã以ä¸ã®ãããªåºåãå¾ããã¾ãã
$ ruby Demo.rb ã¯ã©ã¹ã¿ãªã³ã°éå§(çµæ§æéãããã¾ã) 100 99 98 97 96 95 ... 5 4 3 2 ã¯ã©ã¹ã¿ãªã³ã°çµäº ç»åçæéå§ åºåãã¡ã¤ã«ï¼treemap.png
ããã§ãtreemap.pngã¨ãã以ä¸ã®ãããªç»åãåºåããã¾ãã
ããªã¼ãããã«ãã£ã¦ã¯ã©ã¹ã¿ãªã³ã°ã®çµæãè¦è¦çã«ãããããã表ç¾ããã¦ãããã¨ããããã¨æãã¾ãã
ãã ããå
¥åãã¼ã¿ã¯ã©ã³ãã ã«ä½æãã¦ããã®ã§ãåºåãããç»åã¯æ¯åéããã®ã¨ãªãã¾ãã
以ä¸
ä»åã¯ããã¾ã§ã§ãã
ç´°ããé¨åã¯ããã°ã©ã ã«ã³ã¡ã³ããæ¸ãã¦ããã§ãã¡ããèªãã§ãã ããã
ãã¨ãééã£ã¦ãé¨åãªã©ããã¾ãããæãã¦ããã ããã¨ãããããã§ãã
æ®ãã®ããã°ã©ã ã«ã¤ãã¦ã¯æ¬¡å以é説æãã¾ãã