从Twitter更新校内状态成功!

继续上篇文章,紧天吃午饭的时候觉得那里说的两种方向都不太容易解决。Python的那个最诡异,实在不知道是哪里的问题,而且Python那个脚本,用了几个库,好像我目前手上能用的虚拟主机上(Dreamhost和SDF)都没有;Bash的那个,我实在是不想把目前的宝贵时间花在学习一门新语言上。然后就想到了我过去最喜欢的Perl,既然它被称为是一门“粘合语言”,应该在里面可以直接调用yegle写的wget语句,而且前两天用Perl写过海词客户端简化版,里面就用了正则表达式来处理了HTML。相对与海词的那个排版混乱的HTML输出,Twitter给的XML可简单清晰多了。

我不知道Perl里怎么解析XML,不过Twitter的XML很简单,我几下就弄出了需要的最新的tweet文本和那一条tweet的时间。然后用yegle的wget语句提交,一下子就成功了。然后就发现了一个困扰了我长时间的问题:如果tweet里面是中文,就无法提交(实际上是提交了一个空信息)。然后让程序打印初那条tweet的文字,发现都成了写这样的东西,然后就到处研究怎么把它转换成正常的文字。后来从这里知道了需要用HTML::Entities来处理(代码里第38行)。做了这一步后那些wget语句就又好使了。

结下来就是隔一段时间就运行一下这个程序了。cron似乎是我第一个想到的。还有一个方法就是在Perl脚本里用循环,不过这样似乎有点不妥(具体怎么不妥我没有自习琢磨)。我的MacBook虽然基本上保持开机状态,不过把它放在24小时运行的网上的虚拟主机上似乎更不错。我目前有两个虚拟主机帐号,一个是Dreamhost,一个是SDF。结果两个都有问题:Dreamhost上的wget版本太老,不支持命令行里的那些session、cookies功能;SDF则不让我用cron。SDF的问题不大好办,似乎cron是它们专门的用户帐号才能做的,我目前的ARPA帐号不在此范围。我只好试着下载wget的代码在Dreamhost上编译。结果出乎我意料,居然编译成功了!我过去在不是本地的主机上编译软件通常是以失败而告终的。用了新版本的wget,程序就运行正常了。设定好了cron(我让程序2分钟运行一次,查看了Dreamhost的wiki上关于cron的说明,没有提到有什么限制),程序运行OK。

这时还有最后一个问题没解决:如果让这段代码隔一段时间就自动运行,那么如果在这段时间里面没有更新Twitter,那么校内的状态会被不断用同一条tweet刷新。这也是我要保存最新tweet的发布时间的目的。我用的方法是把这一条tweet的发布时间写到一个磁盘文件中去,然后下一次运行的时候比较两个时间,如果两个时间不同,就运行发布的wget命令,然后更新磁盘文件,否则就退出程序。我不知道有没有更好的解决方案,不过我的方法目前还可行。

最后就是把代码贴出来了。我整理了一下,把用户名、帐号、磁盘文件、还有wget程序的地址都弄成了变量,放在代码最前面以方便设定。完事后看起来还不错。

!/usr/bin/perl -w

Twitter -> Xiaonei status sync tool.

Author: Feng Liu me@liuf.net

Version: 1.0

Date: Tue Apr 21 23:06:40 +0000 2009

use utf8;

use Encode;

use LWP::Simple;

use HTML::Entities;

####################### Settings starts here #######################

Set your base account information here. Don't show this to others!

my $twitter_account = '';

my $xiaonei_email = '';

my $xiaonei_passwd = '';

some machine's wget is too old, so you may need to rebuild a newer

version and indicate the path of your own wget here.

my $wget_cmd = 'wget';

The program needs a log file for keeping the time of your last

tweet. Otherwise you may get your xiaonei status updated to a same

tweet. So please keep this file!

my $logfile = '/tmp/twxn.log';

######################## Settings ends here ########################

my $twitter_url = 'http://twitter.com/statuses/user_timeline/' . $twitter_account . '.xml';

my $statuses = get($twitter_url);

my @lines = split /\n/, $statuses;

my $latest_text = $lines[5];

my $latest_time = $lines[3];

if ($latest_text =~ /(.*)<\/text>/) {

$status = $1;

};

$text = decode_entities($status);

If the log file doesn't exist, create a new one.

if (!(-e $logfile)) {

open LOG,"> /tmp/twxn.log" or die "ERROR: Cannot create log file.";

close LOG;

print "Created a new log file: $logfile\n";

}

open LOG, "< $logfile" || die "ERROR: Cannot open log file!";

$last_time = ;

close LOG;

if ($last_time ne $latest_time) {

my $login_cmd = $wget_cmd . ' --no-proxy -O xiaoneilogin.log --post-data="email=' . $xiaonei_email . '&password=' . $xiaonei_passwd . '&autoLogin=true"  --keep-session-cookies --save-cookies=xiaoneicookie http://login.xiaonei.com/Login.do';

my $post_cmd = $wget_cmd . ' --no-proxy -O xiaoneipost.log --post-data="c=' . $text . '"  --keep-session-cookies --load-cookies=xiaoneicookie http://status.xiaonei.com/doing/update.do --referer=http://status.xiaonei.com/getdoing.do';

system($login_cmd);

system($post_cmd);

open LOG, "> $logfile" || die "ERROR: Cannot open log file!";

print LOG $latest_time;

close LOG;

}

最后,感谢半瓶墨水yegle的指教与启发!

发表评论

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据