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的下载量),使用这一命令行:
$ sudo apt-get install ruby1.9.1-full</div>
接着使用gem实用程序来抓取Twitter gem:
$ sudo gem install twitter</div>
现在你已经有了这一步骤所需的一切了,我们继续,测试一下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"
=> 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>
</div>
接下来,我们来看一下Twitter中的用户的模式,你也可以通过IRB来实现这一点,不过我重排了结果的格式,以便简化对Twitter用户的内部结构的说明。清单2给出了用户结构的输出结果,这在Ruby中是一个Hashie::Mash。这一结构很有用,因为其允许对象有类方法的哈希键访问器(公开的对象)。正如你从清单2中看到的那样,这一对象包含了丰富的信息(用户特定的以及渲染的信息),其中包括了当前的用户状态(带有地理编码信息)。一条tweet消息中也包含了大量的信息,你可以使用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>
</div>
这就是快速展示部分的内容。现在,我们来研究一些简单的脚本,你可以在这些脚本中使用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)

