使用Ruby和Twitter来进行数据挖掘(1)

2008年10月,我像许多人一样满怀好奇地创建了一个Twitter帐户。像大多数人一样,我与一些朋友建立了连接,做一些随机的搜索来更好地理解这一服务。使用140个字符来进行沟通,这看起来好像不太可能是一个受欢迎的想法,但一件无关的事情却让我看到了Twitter的真正价值所在。

2009年7月初,我的网站托管服务提供商熄火了,在进行了一番随意的网络搜索后,我发现信息指向了西雅图Fisher Plaza的一场火灾,这场火是罪魁祸首。传统的基于web的信息源更新很慢,没有提供何时服务会恢复正常的指示。然而,在搜索了Twitter之后,我找到了一些个人帐户对事件的描述,包括了现场实时发生的情况。例如,在我的托管服务恢复正常之前不久,就有一条消息说有柴油发电机位于大厦的外面。

当时我就意识到了Twitter的真正强大之处在于个人以及组织之间的公开的和实时的信息交流。然而,在这一表象下面,则是一个关于用户行为的信息宝库,以及在局部和全局层面上的发展趋势。我使用了Ruby语言和Twitter gem这一Twitter的API包装器来在简单的脚本语境中探讨挖掘的实现,并说明了如何使用其他的web服务和应用来为数据的可视化构建一个简单的混搭应用程序。

Twitter以及一些API

尽管早期的网络涉及的是人-机器的交互,但现在的网络已涉及机器-机器之间的交互,这种交互是使用web服务来支持的。大部分受欢迎的网站都有这样的服务存在——从各种各样的Google服务到LinkedIn、Facebook和Twitter等。通过web服务创建的API,外部的应用可以查询或是操纵网站上的内容。

web服务可以使用多种方式来实现。目前最流行的做法之一是表述性状态转移(Representational State Transfe, REST)。REST的一种实现是通过为人熟知的HTTP协议,允许HTTP作为RESTful架构的媒介存在(使用诸如GET、PUT、POST、DELETE一类的标准HTTP操作)。Twitter的API是作为这一媒介之上的一个抽象来进行开发的。在这一做法中,没有涉及REST、HTTP或是XML或JSON一类的数据格式的知识,而是代之以清晰地整合到了Ruby语言中的基于对象的接口。

Ruby和Twitter的一个快速展示

让我们来探讨一下如何在Ruby中使用Twitter API。首先,我们需要获取所需的资源,如果你像我一样在用Ubuntu Linux®的话,就使用apt框架。

若要获取最新的完整的Ruby分发版本(大约13MB的下载量),使用这一命令行:

    $sudoapt-getinstallruby1.9.1-full

接着使用gem实用程序来抓取Twitter gem:

    $sudogeminstalltwitter

现在你已经有了这一步骤所需的一切了,我们继续,测试一下Twitter的包装器。这一示例使用一个名为交互式的Ruby外壳(Interactive Ruby Shell,IRB)的外壳程序,该外壳程序允许实时地执行Ruby命令以及使用语言进行实验。IRB有着非常多的功能,不过我们只用它来做一些简单的实验。

清单1展示了与IRB的一个会话,该会话被分成了三段以便于阅读。第一段(001和002行)通过导入必需的运行时元素来做好环境方面的准备(require方法加载并执行指定的库)。接下来的一段(003行)说明的是使用Twitter gem来显示从IBM® developerWorks®发出的最新tweet消息。如所展示的那样,使用Client::Timeline模块的user_timeline方法来显示一条消息,这第一个例子说明了Ruby的“链方法”的功能。user_timeline方法返回一个有着20条消息的数组,接着链入到方法first中,这样做是为了从数组中提取出第一条消息(first是Array类的一个方法),接着从这一条消息中提取出文本字段,通过puts方法把它放到输出中。

接下来的一段(004行)使用了用户定义的位置字段,这是一个不限形式的字段,用户可以在其中提供有用的或是无用的位置信息。在这一例子中,User模块抓取了位置字段所限定的用户信息。

最后一段(从005行开始)研究了Twitter::Search模块,这一搜索模块提供了极其丰富的用来搜索Twitter的接口。在这一例子中,首先是创建一个搜索实例(005行),接着在006行指定一个搜索,搜 LulzSec用户在最近发出的包含了why这一词的消息,结果列表已经过删减和编辑。搜索设置会一直存在在那里,因为搜索实例保持着所定义的过滤条件,你可以通过执行search.clear来清除这些过滤条件。

清单1. 通过IRB来实验Twitter API

    $irb irb(main):001:0>require"rubygems"=>trueirb(main):002:0>require"twitter"=>trueirb(main):003:0>putsTwitter.user_timeline("developerworks").first.text dWTwitterissaving#IBMover$600Kpermonth:will#Google+addtothat?> http://t.co/HiRwir7#Tech#webdesign#Socialmedia#webapp#app =>nilirb(main):004:0>putsTwitter.user("MTimJones").location Colorado,USA =>nilirb(main):005:0>search=Twitter::Search.new=>#<Twitter::Search:0xb7437e04@oauth_token_secret=nil, @endpoint="https://api.twitter.com/1/", @user_agent="TwitterRubyGem1.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").eachdo|r|putsr.textend@LulzSecwhynotstopposting<bleep>andgetafulltimejob!MYSQLiisn't hackingyou<bleep>. ... irb(main):007:0>

接下来,我们来看一下Twitter中的用户的模式,你也可以通过IRB来实现这一点,不过我重排了结果的格式,以便简化对Twitter用户的内部结构的说明。清单2给出了用户结构的输出结果,这在Ruby中是一个Hashie::Mash。这一结构很有用,因为其允许对象有类方法的哈希键访问器(公开的对象)。正如你从清单2中看到的那样,这一对象包含了丰富的信息(用户特定的以及渲染的信息),其中包括了当前的用户状态(带有地理编码信息)。一条tweet消息中也包含了大量的信息,你可以使用user_timeline类来轻松地可视化生成这一信息。

清单2. Twitter用户的内部解析结构(Ruby视角)

    irb(main):007:0>putsTwitter.user("MTimJones") <#Hashie::Mash contributors_enabled=false created_at="WedOct0820:40:53+00002008" default_profile=falsedefault_profile_image=false description="PlatformArchitectandauthor(Linux,Embedded,Networking,AI)."favourites_count=1 follow_request_sent=nil followers_count=148 following=nil friends_count=96 geo_enabled=true id=16655901id_str="16655901" is_translator=false lang="en" listed_count=10 location="Colorado,USA" name="M.TimJones" 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=nilcoordinates=nil created_at="SatJul0202:03:24+00002011" favorited=false geo=nil id=86978247602094080id_str="86978247602094080" in_reply_to_screen_name="AnonymousIRC" in_reply_to_status_id=nilin_reply_to_status_id_str=nil in_reply_to_user_id=225663702in_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="UnitedStates"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@AnonakomisPracticalreading forfuturereference...LULZ\&;Prison101\&;http://t.co/sf8jIH9"truncated=false> statuses_count=79 time_zone="MountainTime(US&Canada)" url="http://www.mtjones.com" utc_offset=-25200 verified=false> =>nilirb(main):008:0>

这就是快速展示部分的内容。现在,我们来研究一些简单的脚本,你可以在这些脚本中使用Ruby和Twitter API来收集和可视化数据。在这一过程中,你会了解到Twitter的一些概念,比如说身份验证和频率限制等。

挖掘Twitter数据

接下来的几节内容介绍几个通过Twitter API来收集和呈现可用数据的脚本,这些脚本重点在于其简易性,不过你可以通过扩展以及组合他们来创建新的功能。另外,本节内容还会提到Twitter gem API,这一API中有着更多可用的功能。

需要注意的很重要的一点是,在指定的时间内,Twitter API只允许客户做有限次的调用,这也就是Twitter的频率限制请求(现在是一小时不超过150次),这意味着经过某个次数的使用后,你会收到一个错误消息,并要求你在提交新的请求之前先做一段时间的等待。

用户信息

回想一下清单2中的每个Twitter用户的大量可用信息,只有在用户不受保护的情况下这些信息才是可访问的。我们来看一下如何以一种更便捷的方式来提取用户的信息并呈现出来。

清单3给出了一个(基于用户的界面显示名称)检索用户信息的简单的Ruby脚本,然后显示一些更有用的内容,在需要时使用Ruby方法to_s来把值转换成字符串。需要注意的是,首先用户是不受保护的,否则的话是不能访问到她/他的数据的。

清单3. 提取Twitter用户数据的简单脚本(user.rb)

    #!/usr/bin/envruby require"rubygems"require"twitter"screen_name=String.newARGV[0] a_user=Twitter.user(screen_name) ifa_user.protected!=trueputs"Username:"+a_user.screen_name.to_s puts"Name:"+a_user.name puts"Id:"+a_user.id_str puts"Location:"+a_user.location puts"Usersince:"+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"ListedCnt:"+a_user.listed_count.to_s puts"TweetCnt:"+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"TimeZone:"+a_user.time_zone puts"Verified:"+a_user.verified.to_s puts tweet=Twitter.user_timeline(screen_name).first puts"Tweettime:"+tweet.created_at puts"TweetID:"+tweet.id.to_s puts"Tweettext:"+tweet.text end

若要调用这一脚本,需要确保其是可执行的(chmod +x user.rb),使用一个用户的名称来调用它。清单4显示了使用用户developerworks调用的结果,给出了用户的信息和当前状态(最后一条tweet消息)。这里要注意的是,Twitter把关注你的人定义为followers(粉丝);而把你关注的人称作friends(朋友)。

清单4. user.rb的输出例子

    $./user.rbdeveloperworks Username:developerworks Name:developerworks Id:16362921 Location: Usersince:FriSep1913:10:39+00002008 Bio:IBM'spremierWebsiteforJava,Android,Linux,OpenSource,PHP,Social, CloudComputing,Google,jQuery,andWebdevelopereducationalresources Followers:48439 Friends:46299 ListedCnt:3801 TweetCnt:9831 Geocoded:falseLanguage:en URL:http://bit.ly/EQ7te TimeZone:PacificTime(US&Canada) Verified:falseTweettime:SunJul1701:04:46+00002011 TweetID:92399309022167040 Tweettext:dWTwitterissaving#IBMover$600Kpermonth:will#Google+addtothat?> http://t.co/HiRwir7#Tech#webdesign#Socialmedia#webapp#app

最大的成功在于最大的付出。

使用Ruby和Twitter来进行数据挖掘(1)

相关文章:

你感兴趣的文章:

标签云: