使用Ruby来编写访问Twitter的命令行应用程序的教程
简介
Twitter 现已成为社交网络中的佼佼者。Twitter 只允许用户发布不多于 140 个字符的内容,谁能够想到,这个过去毫不起眼的小网站如今却价值十多亿美元,拥有数百万用户,Twitter 平台上已构建了大量的应用程序,并且不断有新的开发人员准备投入这一浪潮中。
本文并不打算介绍 Twitter(事实上,也没有这个必要)。相反,本文将介绍如何访问 Twitter 平台来构建出色的命令行应用程序。Twitter 支持各种编程语言,包括 C++、Java?、Perl、Ruby、PHP 和 Python。对于每种语言,都有大量的库或包可以帮助您完成大量工作。
本文将介绍如何使用 Ruby 来访问 Twitter。您应该对 Ruby 有所了解,但是即使不具备这方面的知识,也很容易快速掌握 Ruby。
安装 Twitter gem
一些 gem 可用于从 Ruby 访问 Twitter(参见 参考资料,以获得有关的更多信息)。对于本文,我选择使用 twitter,这是由 John Nunemaker 编写的 Ruby 包装器。安装 gem 非常简单:
bash$ gem install twitter
该命令用于在您的机器上安装 Twitter 客户端。如果您有一个定制的 gem 安装文件夹,那么首先需要从脚本中调用 rubygems,然后调用 twitter。下面展示了具体过程:
require 'rubygems' require 'twitter'
第一个 Twitter 脚本
现在,您已经准备好构建第一个应用程序,该应用程序用于检测您所关注的人的位置。首先创建一个脚本,它会获取其他人的姓名,并告诉您他们的当前位置。清单 1 显示了相关代码。
清单 1. 跟踪用户位置
require 'rubygems' require 'twitter' def track ARGV.each do |name| puts name + " => " + Twitter.user("#{name}").location end end
track
这段代码执行了哪些操作?如果您刚刚接触 Ruby,则需要向您解释一下,ARGV 是一个数组,它提供脚本对命令行参数的访问。Twitter.user API 返回有关您对其位置感兴趣的人的信息。调用以下脚本可以获得 Lady Gaga、Ashton Kutcher 和 Oprah Winfrey 的当前位置:
bash$ ./location_tracker.rb ladygaga aplusk Oprah ladygaga => New York, NY aplusk => Los Angeles, California Oprah => Chicago, IL
在 Twitter 上实现用户搜索并了解认证情况
现在,让我们搜索 Twitter 上的一些现有用户。如果可以猜出用户的 Twitter ID,那么可以使用以下命令行:
require 'rubygems' require 'twitter' puts "User exists" if Twitter.user?(ARGV[0])
不过,一般情况下无法猜出用户的 ID。因此,需要提供搜索用户名的功能。这需要用以下代码实现,该代码将搜索名称与 Arpan 匹配的所有用户:
require 'rubygems' require 'twitter' names = Twitter.user_search("Arpan")
但是这段代码未能正常工作。清单 2 显示的错误日志告诉您问题出现在哪里。
清单 2. 无法执行用户搜索
Twitter::Unauthorized: GET https://api.twitter.com/1/users/search.json?q=Arpan% 20Sen: 401: Could not authenticate you. from D:/Ruby/lib/ruby/gems/1.8/gems/twitter-1.6.2/lib/faraday/response/r aise_http_4xx.rb:12:in `on_complete' from D:/Ruby/lib/ruby/gems/1.8/gems/faraday-0.7.4/lib/faraday/response.r b:9:in `call' from D:/Ruby/lib/ruby/gems/1.8/gems/faraday-0.7.4/lib/faraday/response.r b:62:in `on_complete'
从这段代码可以看出,您首先需要通过 Twitter 的认证,然后才能执行其他操作。这里的认证不是要求您进行登录并输入密码;而是指对您的脚本(在Twitter 中称为 应用程序)进行认证。请牢记这一差异,然后访问 http://dev.twitter.com/apps,并使用平常的帐号和密码进行登录。Twitter 会要求您提供应用程序名称、描述和应用程序的占位符 (placeholder) 网站。提供这些信息后,还必须提供以下四项内容实现脚本认证:
- 用户密匙(Consumer key)
- 用户秘密令牌(Consumer secret token)
- 用户 OAuth 密匙
- 用户 OAuth 秘密令牌
现在,在 Ruby 代码内部,您需要使用这些选项填充 Twitter.configure 对象。清单 3 显示了相关代码。
清单 3. 配置脚本进行认证
Twitter.configure do |config| config.consumer_key = "mT4atgBEKvNrrpV8GQKYnQ" config.consumer_secret = "BiQX47FXa938sySCLMxQCTHiTHjuTTRDT3v6HJD6s" config.oauth_token = "22652054-Yj6O38BSwhwTx9jnsPafhSzGhXvcvNQ" config.oauth_token_secret = "o9JuQuGxEVF3QDzMGPUQS0gmZNRECFGq12jKs" end
注意,清单 3 中的条目是虚构的:您需要在脚本中填充自己的内容。顺利完成认证后,就可以搜索名为 Arpan 的人(参见下面的 清单 4)。
清单 4. 在 Twitter 上搜索用户
require 'rubygems' require 'Twitter' Twitter.configure do |config| config.consumer_key = "mT4atgBEKvNrrpV8GQKYnQ" config.consumer_secret = "BiQX47FXa938sySCLMxQCTHiTHjuTTRDT3v6HJD6s" config.oauth_token = "22652054-Yj6O38BSwhwTx9jnsPafhSzGhXvcvNQ" config.oauth_token_secret = "o9JuQuGxEVF3QDzMGPUQS0gmZNRECFGq12jKs" end users = Twitter.user_search(ARGV[0]) users.each do |user| print "\n" + user.name + " => " print user.location unless user.location.nil? end
现在,将脚本保存为 search_for.rb,并在命令行中以 ./search_for.rb Arpan 形式调用脚本后,您将获得 清单 5 所示的用户名称。
清单 5. 清单 4 的代码输出
Arpan Jhaveri => New York Arpan Boddishv => Arpan Peter => Bangalore,India Arpan Podduturi => NYC Arpan Kumar De => IIT Kharagpur Arpan Shrestha => Kathmandu, Nepal Arpan Divanjee => Mumbai,India Arpan Bajaj => Bay Area, CA
您可能期望获得更多结果。Arpan 这个名字(印度姓名)并不少见,那么为什么搜索结果这么少?最后您会发现,user_search 使用了一个可选参数(一个 Ruby hash 表),您也可以指定可产生更多结果的选项。因此,可以稍微修改一下清单 5 的代码,传递可选的 hash 参数(#)并预填充它的值。例如,如果希望在一个页面中填充 15 项结果,那么可以使用 清单 6 中的代码。
清单 6. 在每个页面显示 15 项搜索条目
require 'rubygems' require 'twitter' #.. authentication code here users = Twitter.user_search(ARGV[0], {:per_page => 15}) #... same as Listing 10
是不是可以在每个页面中显示 100 项条目?不行,Twitter.user_search 允许每页显示的最多条目为 20。清单 7 显示了如何在每个页面中显示 20 个条目。
清单 7. 每个页面显示 20 个条目
#... usual authentication stuff pagecount = 0 while pagecount < 10 u = Twitter.user_search("#{ARGV[0]}", {:per_page => 20, :page => pagecount}) u.each do |user| print "\n" + user.name + " => " + user.screen_name print " => " + user.location unless user.location.nil? end unless u.size < 20 pagecount += 1 end
现在看上去好多了。您现在可以根据偏好名和用户的屏幕名称搜索用户,下面让我们做一些更有趣的事情。让我们搜索居住在纽约的、喜欢 Ruby 的名为 Nick 的人。您可以从 user_search 获得姓名和位置,但是如何处理喜欢 Ruby 的搜索要求?这引入了下一个需要学习的内容:创建定制搜索客户端。
使用 Twitter::Search 类
使用 Twitter::Search 类创建定制搜索客户端。清单 8 显示了相关代码。
清单 8. 学习使用 Twitter::Search 类
#... user authentication pagecount = 0 while pagecount < 10 u = Twitter.user_search("#{ARGV[0]}", {:per_page => 20, :page => pagecount}) u.each do |w| if w.location == "New York" results = Twitter::Search.new.from(w.screen_name).containing("ruby").fetch puts w.screen_name if results.size > 10 end end unless u.size < 20 pagecount += 1 end
这里发生了什么呢?代码首先使用 Twitter::Search.new 创建了一个搜索客户端。接下来,要求搜索客户端从包含 ruby 的相应用户那里获取所有 tweet。最后,代码返回一组结果,如果在 tweet 中提到 Ruby 的次数超过十次,则将此人定义为喜欢 Ruby 的人。
让我们尝试为 hash 标记 #ruby 获取一组 tweet。下面是具体实现:
#... user authentication code results = search.hashtag("ruby").fetch results.each do |r| puts r.text + " from " + r.from_user end
不过,还可以实现更多内容。对于 ruby 之类的 hash 标记,您希望获得数百个条目,不是吗?对于这种情况,使用搜索客户端也会带来便利,因为您可以从搜索客户端轻松地检索下一个页面。清单 9 的代码显示了有关 Ruby 的十页 tweet。
清单 9. 显示多个页面
更多搜索选项
搜索客户端可以让您实现更出色的功能,比如使用特定语言或来自某个地方(比如德国)的 tweet。您甚至可以搜索提到特定用户的 tweet,或搜索匹配特定条件的 tweet。例如,搜索所有提到 Ruby 但没有提到 Rails 的 tweet?尝试下面的代码:
search.containing("ruby").not_containing("rails").fetch
当然,您可以像下面这样进行串联:
search.containing("ruby").not_containing("rails").mentioning("username").from("place-id")
搜索短语非常直观。例如,输入以下代码:
search.phrase("ruby on rails").fetch
现在,您已经掌握了入门要领!
速度限制
关于 Twitter,您需要了解一件重要的事情,即速度限制,Twitter 非常重视这个问题。速度限制意味着 Twitter 只允许您的脚本每个小时执行有限次数的查询。您可能已经发现,对于某些应用程序,您不需要进行显式的认证,但是对于另外一些应用程序,认证则是必须的。对于不包含 OAuth 标记的应用程序,当前的最大限制是每小时执行 150 个调用;对于带有该标记的应用程序,允许每小时执行 350 个调用。有关 Twitter 速率限制的最新信息,请查看 参考资源。要了解您的脚本认证的当前限制,请添加以下代码:
puts Twitter.rate_limit_status
下面是输出结果:
<#Hashie::Mash hourly_limit=350 remaining_hits=350 reset_time="Sat Aug 13 21:48: 59 +0000 2011" reset_time_in_seconds=1313272139>
如果您希望获得更具体的结果,请用代码查看下面的内容:
Twitter.rate_limit.status.remaining_hits
下面的输出禁用了认证。注意,您已经用完了可用限制的 50%:
<#Hashie::Mash hourly_limit=150 remaining_hits=77 reset_time="Sat Aug 13 21:13:5 0 +0000 2011" reset_time_in_seconds=1313270030>
更新 Twitter 的状态,重新发布 tweet 和其他内容
搜索功能暂时告一段落。现在需要使用脚本更新 tweet 的状态。只需一行代码即可(当然,您需要在脚本中包含认证代码):
#... authentication code Twitter.update (ARGV [0])
将代码保存为 update.rb,并以 ruby update.rb "Hello World from Ruby Script" 的形式从命令行调用它。现在,您的 Twitter 页面已经实现了更新!对话功能是 Twitter 的一个自然扩展,向另一个用户发送消息非常简单:
#... authentication code Twitter.direct_message_create("username", "Hi")
您可以选择使用用户的屏幕名或数字 ID 发送消息。Twitter 的另一个有趣特性是可以快速查看最近发送的和最近接收到的 20 条消息:
#... authentication code Twitter.direct_messages_sent.each do | s | puts "Sent to: " + s.recipient_screen_name puts "Text: " + s.text end
我们有时候需要强调某些 tweet 的重要性,一个好方法就是重新发布 tweet。下面显示了重新发布的最近 20 个 tweet:
#... authentication code Twitter.retweets_of_me.each do |rt| print rt.text puts " retweet count = " + rt.retweet_count.to_s end
当然,如果能知道是谁在重新发布 tweet 就更好了,但是无法从 retweets_of_me API 直接获取该信息。相反,您需要使用 retweeters_of API。注意,每个 tweet 都有一个唯一的 ID,而 retweeters_of 需要获得这一 ID。清单 10 展示了相关代码:
清单 10. 谁在向我重新发布 tweet
#... authentication code Twitter.retweets_of_me.each do |rt| print rt.text print " retweeted by " Twitter.retweeters_of(rt.id).each do |user| puts user.screen_name end end
用 Twitter 实现有趣的功能
您可以利用自己的脚本做许多有趣的事情。例如,假如您很关心当前 Twitter 中正在发生的事情,那么您可以获取前十个趋势:
Twitter.trends.each do | trend | puts trend.name end
twitter.com 只能报告前十个趋势。参考 参考资源,获得有关的更多信息。通常,您可能只关心所在地的趋势。只需要提供所在地的 where-on-earth ID (WOEID),Twitter 就可以提供这些信息。下面我展示了如何获得印度的当前趋势:
Twitter.local_trends(12586534 ).each do | trend | puts trend #local_trends returns String end
获得 Twitter 推荐的用户也很容易。首先查看以下脚本:
Twitter.suggestions("technology").users.each do | user | puts user.screen_name end
我对这段代码的输出进行了仔细检查。前十个结果意味着这段代码可以正常工作。Twitter 提供了不同的用户感兴趣的类别,通过调用 Twitter.suggestions(只需将 Twitter.suggestions 放在脚本里)便可获得此信息。每个类别都有一个简短名称,在 Twitter 中称为 slug,您需要将其传递给 Twitter.suggestions,然后便可获得 Twitter 推荐的用户。清单 11 展示了相关输出。
清单 11. 技术类别中推荐的前几名用户
gruber
dannysullivan
AlecJRoss
timoreilly
Padmasree
tedtalks
OpenGov
twitter
BBCClick
woot
anildash
laughingsquid
digiphile
jennydeluxe
biz
ForbesTech
chadfowler
leolaporte
本文最后将介绍如何找到 Sachin Tendulkar(最棒的板球队员)的最受欢迎的粉丝。首先,Sachin 的 ID 是 sachin_rt(在相关主题上,您可以使用 Twitter.user("sachin_rt").follower_count 查看其粉丝的数量,并使用 Twitter.user("sachin_rt").verified 确认他的状态)。
现在,使用 Twitter.follower_ids("sachin_rt") 获得 Sachin 粉丝的数量。默认情况下,您将获得 5000 名用户,这足够支持您完成下面的工作。确保您已经阅读 Twitter 文档并参考了 Twitter 的 API resources for friends and followers,了解如何获得完整的粉丝列表。下面是一个代码示例:
#... authenticate yourself puts Twitter.follower_ids("sachin_rt").ids.size
最后,根据 follower_count 对这 5000 名用户中的某些用户进行排序:
#... authenticate yourself puts Twitter.follower_ids("sachin_rt").ids[0..49].sort!{|a, b| \ Twitter.user(a).followers_count <=> \ Twitter.user(b).followers_count}.reverse.first.name
在 sort 之后,"!" 表示排序对所调用的内容修改了数组(并且没有返回新的数组),花括号({})中的代码是比较功能。这解释了使用 Ruby 的另一个原因:能够在一行代码中实现 20 行 C++ 代码完成的工作。
结束语
为 Twitter 编写命令行脚本非常有趣,并且可以使您洞悉 Twitter 尚未提供的功能。此外,无论是搜索符合您的条件的特定用户(从本地技术人员到领域中的主题专家),还是搜索令人兴奋的新 tweet,都可以很方便地通过命令行来实现。在结束本文之前,我需要给出最后两条忠告:首先,Twitter 非常在意每小时的速率限制,因此最好将搜索结果缓存到您的代码中。其次,随时关注 Twitter 的 REST API 资源,其中列出了您的 Twitter 客户端的所有 API。最重要的是,尽情享受 Twitter 的乐趣!