操作系统

功能丰富的Perl:Flickr,业务最好的朋友
作者 Send_linux 2009年12月27日 16:00
级别: 初级

Teodor Zlatanov, 程序员, Gold Software Systems

2009 年 12 月 28 日

Flickr 不仅仅意味着照片共享和社会网络;它还是一个良好的业务工具。了解 Perl 程序员如何使用 CPAN Chart 模块创建图表和图形,以及如何使用 Flickr::Upload 模块将图表上传到 Flickr。
与 Ted 联系
Ted 是我们的最受欢迎的和最多产的作者之一。查看 Ted 的个人资料 并与他以及 My developerWorks 上的其他作者和读者联系。

Flickr 绝对是世界上最好的图片共享网站,可以在这里找到各式各样的图片,有可爱的小狗、稍微有些没对准焦点的日落,还有婚礼蛋糕。很难将其看作是业务中心,但是本文将展示一些途径,可以通过 Perl 来将 Flickr 打造成一个更加面向业务的站点。

Flickr 的一项常见业务应用一直以来都是展示产品。这对于销售实体产品的公司来说非常棒,特别是那些可以从视觉曝光获益的公司。这里没有必要对此进行深入探讨 — 数十种可用工具都可以将产品组合很好地上传到 Flickr。

相反,我将展示如何使用 CPAN 模块(最初由 Dave Bonner 开发,现在由 Chart 小组维护)构建一个自定义图表,以用于商业用途。我们将查看一年当中的股票收益的表现(使用虚构数据),然后在 Flickr 相册中发布该图表,这个相册展示了过去的性能图表。我们将只使用对这个应用程序有意义的 Flickr 特性,因此不会涉及完整的 Flickr API。因此,应当访问 API 站点并通读文档。文档易于阅读并且非常全面;通过 Perl 使用它非常简单。

Chart::???? 模块在哪?

实际上并不存在 Chart::[type] 模块。所有不同的图表类型 —点、线、条、LinesPoint、合成图、StackedBar、饼图、Pareto、HorizontalBars、Split、ErrorBars、Direction 和 Mountain — 本身都自成一类,每一种都从 Chart::Base 类继承了大量方法。要使用其中的一种,只需使用所需的图表类型替换 [type],如下所示:

use Chart::Lines;

您可以对图表使用 Google API,但是撰写本文之际,使用 Perl 的 Chart 模块可以比使用 Javascript 的 Google Charts API 完成更多的功能。但是,这一情况可能会改变,因此您应该继续关注 Google 的工具。

我们的目标

首先,让我们为图表随机生成数据并直接将其置于列表中。通常来讲,数据将来自文件或数据库,但是我们将跳过这一步,因为这并不重要。

我将使用该列表来以图形方式创建图表,该图表随后可被上传到 Flickr,并加以正确标记和适当的描述。很简单,对不对?

当您安装 Chart 模块时,记住您不能只安装 “Chart”,例如,您还需要安装 “Chart::Lines”。







生成随机数据

生成随机数据是很简单的事,因此让我们从数字 100 开始并从每个连续数据点的前一个数据点生成一个随机的偏移,要获得 200 个数据点,随机增加或减少的量不能超过 0.5。目前为止只需要在虚构示例中实现这些操作,但是使用 composite 图表标记曲线的首尾、计算 MACD 等等,将是一个有趣的项目。如果您喜欢探索的话,那么继续深入下去。


清单 1. chart_uploadr.pl:生成随机数据
				
my $max = 200;         # the maximum data points

# generate random data and labels for it
my @data = ([100], [100]);
my @labels = (0);

foreach (1..$max)
{
 # I know there are 20 options for skipping ticks, but this works better for me
 push @labels, every(25) ? $_ : undef ;

 # the delta is from [ -.5 up to .5 )
 foreach my $array (@data)
 {
  push @$array, $array->[-1];
  $array->[-1] += (0.5 - rand 1);
 }
}

下面是具体思路:从包含两个数组(每个数组一个元素)的 @data 开始。这是两个数据集的起始值。标签也只包含一个起始的零。现在,执行 200 次如下操作:向 @labels 列表添加与当前循环迭代相等的标签(每 25 次添加一个标签,总共添加 200/25 = 8 个标签);然后将每个数据集的最新值复制到相同数据集,并对新的最新值应用一个随机的向上或向下的调整。不需要临时变量。

应该指出,这里使用了 CPAN Every 模块来插入空的内容(一个 undef 值)或 @labels 列表的当前循环迭代。我知道有许多 Chart 选项可以跳过标签,但是这是一种更简单的解决方案。我还想展示 every() 函数,它提供一个数字,它在得到多次调用后将只返回一次 true。(因此 every(2) 将在第 2 次、第 4 次、第 6 次……得到调用时返回 true)。我编写了 Every 模块,并且我发现这样使用它以及将它用于调试会非常方便。

调整幅度在 -0.5 和 0.5 之间(准确来讲,不包括 0.5)。以 100 为起始值,这样做比较合理。







生成图表

CPAN Chart 模块十分出色并且可以减轻您的工作。它们使用 GD 库。如果有疑问的话,阅读安装说明并上网搜索。Chart 模块附带了 Documentation.pdf 文件,其中包含了所有模块的所有文档以及每种表类型的示例。

准备好一切内容后,生成 PNG 图表将非常简单:


清单 2. 创建图表
				
my $save_name = "performance.png";   # file name to use

my $title = "Performance of MoneyCo funds over 200 days";
my $desc = "Total value at EOD starting " . 
           strftime("%Y-%m-%d", localtime);

my $chart = Chart::Lines->new(800,600);
$chart->set(title => $title,
            sub_title => $desc,
            x_label => "days",
            y_label => "millions USD",
            legend => "bottom",
            legend_labels => [ "Aggressive Fund", "Passive Fund" ],
            y_grid_lines => "true",
           );

$chart->png($save_name, [ \@labels, @data ]);

die "Couldn't create $save_name: $!" unless -f $save_name && -r $save_name;

我们使用一个标题、一个描述性的副标题、X 和 Y 标签设置了一个图表,将图例放在了底部,并对两个数据集使用标签。最后,我们使用了 Y 网格线(从左到右)。这样,金额数可以很轻易地显示出来。

标题应当包含当前日期,这样当在 Flickr 照片流中有多个图表上传时就会很有意义。不管您希望使用什么日期格式,确保使用来自 POSIX 模块的 strftime 函数生成日期格式。毫无疑问,在过去 15 年中最让我痛恨的 Perl 代码问题源于作者不会使用 POSIX::strftime() 函数。

使用 png() 方法调用,图表被保存为 $save_name variable 的 PNG 文件。







Flickr 身份验证和授权

应用程序必须使用两个参数运行,第三个参数为可选参数:


清单 3. 命令行参数
				
my $api_key    = shift @ARGV;
my $secret     = shift @ARGV;
my $auth_token = shift @ARGV;

die "Syntax: $0 API_KEY SECRET [AUTH_TOKEN]" unless defined $secret;

这是一种执行命令行选项的真正简单的方法。您可能希望使用 Getopt::Long。它需要两个参数,并且如果没有给出使用方法的话,那么就会失败。

API 密匙和秘密可以从 Flickr 获得。除非您知道自己需要商业用途的密匙,否则申请一个非商业用途的密匙,您将立刻获得它。这两个参数将对您的应用程序进行身份验证(chart_uploadr.pl)。

现在,如果还没有提供 $auth_token(第三个命令行参数),脚本将在您的帮助下获得它(我从 Flickr::Upload、FIXMEs 等附带的 flickr_upload 脚本复制了该方法)。

没有令牌的话就不能执行上传操作。令牌向经过身份验证的应用程序授权,以向 Flickr 上传内容。因此运行应用程序的用户 将看到一个 URL,要使应用程序上传内容,必须访问这个 URL。用户可以是请求 API 密匙的同一个用户,但是不是必须的。

我们创建一个 $ua 变量(LWP::UserAgent 类型的对象)来与 Flickr 服务器交互。您应当查看 LWP::UserAgent 文档;该模块对于任何使用 Perl 编写的 Web 客户机都非常重要。许多其他优秀的模块,比如 WWW::Mechanize,都依赖于 LWP::UserAgent


清单 4. 身份验证和授权
				
my $ua = Flickr::Upload->new({
                              'key' => $api_key,
                              'secret' => $secret,
                             });

# from the flickr_upload script that comes with Flickr::Upload
unless (defined $auth_token)
{
 # 1. get a frob
 my $frob = getFrob( $ua );

 # 2. get a url for the frob
 my $url = $ua->request_auth_url('write', $frob);

 # 3. tell the user what to do with it
 print "1. Enter the following URL into your browser\n\n",
  "$url\n\n",
   "2. Follow the instructions on the web page\n",
    "3. Hit <Enter> when finished or Control-C to exit.\n\n";
        
 # 4. wait for enter.
 <STDIN>;

 # 5. Get the token from the frob
 my $auth_token = getToken( $ua, $frob );
 die "Failed to get authentication token!" unless defined $auth_token;
        
 # 6. Tell the user what they won.
 print "Your authentication token for this application is\n\t\t",
  $auth_token, "\n";

 exit 0;
}

# from the flickr_upload script that comes with Flickr::Upload
sub getFrob
{ 
 my $ua = shift;

 my $res = $ua->execute_method("flickr.auth.getFrob");
 return undef unless defined $res and $res->{success};

 # FIXME: error checking, please. At least look for the node named 'frob'.
 return $res->{tree}->{children}->[1]->{children}->[0]->{content};
}

sub getToken
{
 my $ua = shift;
 my $frob = shift;

 my $res = $ua->execute_method("flickr.auth.getToken",
                   { 'frob' => $frob } );
 return undef unless defined $res and $res->{success};

 # FIXME: error checking, please.
 return $res->{tree}->{children}->[1]->{children}->[1]->{children}->[0]->{content};
}

如果在不需要 URL 访问的情况下,Flickr 就能够为您提供一种获得授权令牌的方法,那该多好,但是目前还无法实现这一点,因此您必须使用 URL。这是一个一次性事物;一旦拥有了授权标记,您可以一直使用它,直到人类灭绝、Flickr 服务器被关闭,或者您不再需要上传内容 — 不管首先出现哪一个原因。

另外,我希望 Flickr 可以在其 API 文档中区分身份验证和授权。这是两种截然不同的东西,如果将两者混淆,那么会误导用户。(这是来自 Word Police 的一条消息,谢谢)。

获得令牌后,要运行应用程序,只需要输入:

./chart_uploadr.pl key secret token

并且,如果一切顺利的话,那么将安静地退出。







实现上传!

最后,我们可以实际上传图像。


清单 5. 上传
				
$ua->upload(
            photo       => $save_name,
            title       => $title,
            description => $desc,
            auth_token  => $auth_token,
            tags        => 'MoneyCo fund performance',
            is_public   => 1,
            is_friend   => 1,
            is_family   => 1
           ) or die "Failed to upload $save_name: $!";

这一部分非常简单。您可以使用许多参数,在 Flickr Upload API(参见 参考资料)中均有记录。photo 参数指向实际的文件。titledescription 与我们在生成图表时用于标题和副标题的内容相同。标记目前是静态的,但是可以适用于生成的任何图表。最后,所有 is_whatever 参数使图像可以完全地、真正地、绝对地公开化。

http://www.flickr.com/photos/58365921@N00/3497574717/ 提供了一个上传示例。

现在,当授权了 chart_uploadr.pl 的用户在他们的照片流中看到这幅被上传的图像后,那么大功告成。







结束语

您创建了随机的数据来表示股票业绩,并从这些数据中使用 PNG 文件的形式创建了一个简单的股票图表,并将此 PNG 文件上传到 Flickr。整个过程全部自动完成。

当然,在实际中,数据不会是随机的。您必须编写代码来从文件或数据库获取数据。绘制数据每次都将生成一致的结果。

给您的忠告:可以让图表变得更好。参考一下财务图表以获得灵感;常见的改进包括使用更好的标签、指出最大和最小值,等等。这是一个非常有意义的项目,因为外观漂亮的图表总是能够吸引客户,反过来,使用更好的 Getopt 模块改进上传过程并不会使客户留下深刻印象。换句话说,如果您必须生成一个可视的产品,那么一定要让它具有专业的外观。

祝您上传顺利!








下载

描述名字大小下载方法
样例脚本chart_uploadr.zip2KBHTTP
关于下载方法的信息


打开APP阅读全文

功能丰富的Perl:Flickr,业务最好的朋友

功能丰富的Perl:Flickr,业务最好的朋友

长按识别二维码 进入IT168查看全文

请长按保存图片
{{data.thematic.text}}

相关文章

加载中...

分享到

请使用浏览器的分享功能
分享到微信等