Work the Shell - 将您的消息推送到 Twitter

作者:Dave Taylor

天哪,我们真的已经为电影问答 Twitter 流工作了快一年了吗?这肯定是软件开发历史上每行代码耗时最长的项目了。

之前的专栏文章结合起来,为我们提供了一组 shell 脚本,这些脚本抓取互联网电影数据库 (IMDb, www.imbd.com) 的前 250 名列表,然后提取每部电影的发行年份(不方便的是,在与前 250 名列表相同的页面上不可用),随机选择合理的错误发行年份猜测,并以以下形式输出问题:“IMDB Top 250 电影 #81:电影《2001:太空漫游》是在 1968 年、1973 年还是 1975 年发行的?”

这背后的工作比您可能意识到的要多得多。当然,如果您一直在阅读之前的专栏文章,您实际上已经亲身了解了我们不得不经历多少麻烦(但幸运的是,没有“成桶的真火”)。

本月,我们将把注意力转向 Twitter 微型博客服务,因为我们最终有能力生成所需的消息。现在,我们只需要一种机制将其发布到 Twitter。

破解 Twitter API

我可以走弯路,实际阅读 Twitter API 以学习如何进行特定调用并以优雅和适当的方式与服务交互,但这听起来像工作,不是吗?

事实证明,有一种简单的方法可以通过命令行 Web 实用程序调用 Twitter,并访问大部分基本数据。我选择的工具?Curl,一个简洁的实用程序,可以更轻松地通过命令行使用互联网服务。

URL 是 twitter.com/statuses/update.json,但传递数据的方式有点棘手。您需要将其作为 name=value 对在连接流中发送,而不是作为 GET 值或其他基于 URL 的技术。它寻找的变量是 status,您可以通过执行以下操作对其进行测试

$ curl --data-ascii status=testing \
http://twitter.com/statuses/update.json

问题在返回消息中立即显现出来

Could not authenticate you.

啊,好吧,是的,我们还没有指定我们的用户 ID。这些凭据不是通过 URL 或 --data-ascii 发送的,而是通过基本的 HTTP 身份验证发送的。所以,实际上,您需要这样做

$ curl --user "$user:$pass" --data-ascii \
status=testing "http://twitter.com/statuses/update.json" 

现在,当然,您需要一个 Twitter 帐户才能使用。对于这个项目,我将继续使用 FilmBuzz,这是一个我也设置用来传播有趣的电影行业新闻的 Twitter 帐户。

为了本文的目的,让我们假设密码是 DeMille,当然,这不是真的密码。可以设置 user 和 pass 变量,然后我们调用 Curl 来看看会发生什么

$ curl --user "$user:$pass" --data-ascii status=testing
http://twitter.com/statuses/update.json
{"truncated":false,"in_reply_to_status_id":null,"text":
↪"testing","favorited":null,"in_reply_to_user_id":
↪null,"source":"web","id":880576363,"user":{"name":
↪"FilmBuzz","followers_count":214,"url":null,
↪"profile_image_url":"http:\/\/s3.amazonaws.com\
↪/twitter_production\/profile_images\/55368346\
↪/FilmReelCloseUp_normal.JPG","description":"Film
↪trivia game, coming soon!","location":"Hollywood, of
↪course","screen_name":"FilmBuzz","id":15097176,"protected":
↪false},"created_at":"Thu Aug 07 16:51:49 +0000 2008"}

返回的数据让您很好地了解了 FilmBuzz twitter 帐户的配置,并告诉您我们发送的内容不太长 (truncated:false),但除此之外,它相当容易被遗忘,不是吗?

如何在 shell 中使用命令忽略输出?当然是将输出重定向到 /dev/null

$ curl --user "$user:$pass" --data-ascii status=testing
http://twitter.com/ses/update.json > /dev/null
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 505 100 505 0 0 1127 0 --:--:-- --:--:-- --:--:-- 0

不,这不起作用,因为那样 Curl 想要给我们一些事务统计信息。我们如何掩盖这一点?使用 Curl 的 --silent 标志。现在,我们差不多完成了

$ curl --silent --user "$user:$pass" --data-ascii status=testing
http://twitter.com/statuses/update.json > /dev/null
$

就是这样。让我们将其放入 shell 脚本中,这样我们就可以简单地使用 tweet 调用我们要发送给 FilmBuzz 关注者的消息。(而且,如果您还没有在 Twitter 上关注 FilmBuzz,那还等什么?访问 twitter.com/FilmBuzz,然后点击关注。)实际上,我们需要考虑一件事:虽然我们在命令行上的消息很可能包含空格,但我们不能发送带有空格的 name=value 对。相反,快速调用 tr 让我们将所有空格转换为 + 号,这是普遍接受的 HTTP 编码

#!/bin/sh
# Twitter command line interface
user="FilmBuzz" ; pass="DeMille"
curl="/usr/local/bin/curl"

$curl --silent --user "$user:$pass" --data-ascii \
"status=$(echo $@ | tr ' ' '+')" "http://twitter.com/
↪statuses/update.json"
> /dev/null
exit 0

这不是一个特别强大的解决方案,因为如果我们要传输的消息中有一个 + 字符会发生什么?它会丢失。这可以通过首先检查是否有没有 + 号并将它们转换为安全的 HTTP 编码等效项 %2B 来解决。但是,您不能使用 tr 执行此操作,因为它需要 1:1 替换,因此我们将改用 sed,并将替换拉到自己的行上,以获得更好的样式

msg=$(echo $@ | sed 's/+/%2B/g;s/ /+/g')

$curl --silent --user "$user:$pass" --data-ascii \
"status=$msg" "http://twitter.com/statuses/update.json" > /dev/null

问题解决了。现在您可以做一些简单的事情,例如

$ tweet 'Tweeting from the command line? Well, sure!'

不错。现在,将所有内容放在一起。哦。我们空间不够了。又一次。好吧,下个月。我们终于拥有了所需的所有构建块。请记住,注册 Twitter,然后关注 @FilmBuzz,这样您就可以看到这项工作的成果。

Dave Taylor 是一位拥有 26 年 UNIX 经验的资深人士,Elm Mail System 的创建者,以及最近畅销书 Wicked Cool Shell ScriptsTeach Yourself Unix in 24 Hours 的作者,他是 16 本技术书籍的作者。他的主要网站是 www.intuitive.com,他还通过 AskDaveTaylor.com 提供技术支持。通过 twitter.com/DaveTaylor 在 Twitter 上关注 Dave。

加载 Disqus 评论