使用Perl在终端获取天气预报

获取天气预报可能是一项繁琐的工作;您需要导航到正确的网站,关闭横幅广告,输入您的位置,点击正确的链接,也许您才能看到预报。我想找到一个更方便的方法,并找到了使用WWW::Wunderground::API的方式。正如其名所示,该模块提供了一个访问Wunderground.com API的Perl接口。在这篇文章中,我将向您展示如何使用它。

设置

您需要一个Wunderground.com的API密钥(在此注册,免费)。您还需要安装WWW::Wunderground::API。CPAN测试者的结果显示,它可以在包括Windows在内的大多数平台上运行。您可以在命令行中安装该模块

$ cpan WWW::Wunderground::API

代码

使用WWW::Wunderground::API,我创建了一个脚本来获取我所在城市的逐小时预报

#!/usr/bin/env perl
use strict;
use warnings;
use WWW::Wunderground::API;

binmode STDOUT, ':utf8'; # for degrees symbol

my $w = new WWW::Wunderground::API(
    location => 'New York City, NY',
    api_key  => '123456789012345',
    auto_api => 1,
);

# print header
printf "%-10s%-4s%-4s%-8s%-20s\n",
       'Time',
       "\x{2109}",
       "\x{2103}",
       'Rain %',
       'Conditions';

# print hourly
for (@{ $w->hourly })
{
    printf "%8s%4i%4i%8i  %-30s\n",
           $_->{FCTTIME}{civil},
           $_->{temp}{english},
           $_->{temp}{metric},
           $_->{pop},
           $_->{condition};
}

在脚本中,我使用code>binmode将标准输出切换到UTF8模式。这让我可以稍后打印一些酷炫的度数符号。然后我连接到Wunderground API,传递我的API密钥和位置(位置可以是城市名或邮政编码)。最后,我使用printf格式化输出打印天气预报。我将脚本保存为weather并在命令行中运行它

$ weather
Time            Rain %  Conditions
11:00 PM  69  21       3  Partly Cloudy
12:00 AM  69  21       3  Partly Cloudy
 1:00 AM  69  21       8  Partly Cloudy
 2:00 AM  69  21       9  Mostly Cloudy
 3:00 AM  69  21       8  Mostly Cloudy
 4:00 AM  69  21       5  Mostly Cloudy
 5:00 AM  69  21       5  Overcast
 6:00 AM  69  21       4  Overcast
 7:00 AM  69  21       4  Mostly Cloudy
 8:00 AM  70  21       4  Mostly Cloudy
 9:00 AM  72  22       3  Mostly Cloudy
10:00 AM  74  23       2  Mostly Cloudy
11:00 AM  77  25       2  Mostly Cloudy
12:00 PM  80  27       2  Mostly Cloudy
 1:00 PM  82  28       1  Mostly Cloudy
 2:00 PM  84  29       7  Overcast
 3:00 PM  84  29      46  Chance of a Thunderstorm
 4:00 PM  84  29      52  Chance of a Thunderstorm
 5:00 PM  82  28      56  Chance of a Thunderstorm
 6:00 PM  82  28      45  Chance of a Thunderstorm
 7:00 PM  81  27      50  Chance of a Thunderstorm
 8:00 PM  80  27      39  Chance of a Thunderstorm
 9:00 PM  78  26      32  Chance of a Thunderstorm
10:00 PM  77  25      38  Chance of a Thunderstorm
11:00 PM  74  23       6  Partly Cloudy
12:00 AM  71  22       3  Clear
 1:00 AM  69  21       3  Clear
 2:00 AM  67  19       2  Partly Cloudy
 3:00 AM  65  18       2  Clear
 4:00 AM  64  18       2  Clear
 5:00 AM  62  17       2  Clear
 6:00 AM  61  16       2  Clear
 7:00 AM  60  16       2  Clear
 8:00 AM  60  16       2  Clear
 9:00 AM  62  17       1  Clear
10:00 AM  64  18       0  Clear

结果显示了逐小时预报,包括华氏和摄氏温度,降雨概率以及总体描述。由于我大部分工作都在终端进行,所以这比使用浏览器方便得多,而且没有广告!

多个位置

所以这个脚本不错,但我们如何让它更好呢?好吧,我很少一直在同一个地方,我想大多数人也是如此,所以让它更加灵活,让用户输入位置,而不是每次都使用相同的位置会很好

#!/usr/bin/env perl
use strict;
use warnings;
use WWW::Wunderground::API;

my $home_location = 'New York City, NY';

# capture location
print "Enter city or zip code ($home_location): ";
my $location = <>;
chomp $location;

binmode STDOUT, ':utf8'; # for degrees symbol
my $w = new WWW::Wunderground::API(
    location => $location || $home_location,
    api_key  => '123456789012345',
    auto_api => 1,
);

# print header
printf "%-10s%-4s%-4s%-8s%-20s\n",
       'Time',
       "\x{2109}",
       "\x{2103}",
       'Rain %',
       'Conditions';

# print hourly
for (@{ $w->hourly })
{
    printf "%8s%4i%4i%8i  %-30s\n",
           $_->{FCTTIME}{civil},
           $_->{temp}{english},
           $_->{temp}{metric},
           $_->{pop},
           $_->{condition};
}

我已经更新了代码,将默认位置存储为$home_location。然后我要求用户输入城市或邮政编码,确保使用chomp处理结果。在API调用中稍后,代码:$location || $home_location将提交默认位置,除非用户输入了位置。现在运行脚本,我可以轻松地获取伦敦的天气预报

$ weather
Enter city or zip code (New York City, NY): London, UK
Time            Rain %  Conditions
 4:00 AM  50  10       4  Clear
 5:00 AM  50  10       4  Clear
 6:00 AM  49   9       4  Clear
 7:00 AM  49   9       4  Clear
 8:00 AM  52  11       4  Clear
 9:00 AM  55  13       4  Clear
10:00 AM  59  15       4  Clear
11:00 AM  62  17       3  Clear
...

缓存

WWW::Wunderground::API》文档显示了如何使用《Cache::FileCache》在本地缓存天气结果。当您设置缓存时,您可以指定一个过期参数——在缓存过期之前,WWW::Wunderground::API将使用缓存的结果而不是Wunderground API。这避免了不必要的API调用并使脚本运行更快

#!/usr/bin/env perl
use strict;
use warnings;
use WWW::Wunderground::API;
use Cache::FileCache;

my $home_location = 'New York City, NY';

#capture location
print "Enter city or zip code ($home_location): ";
my $location = <>;
chomp $location;

binmode STDOUT, ':utf8'; # for degrees symbol
my $w = new WWW::Wunderground::API(
    location => $location || $home_location,
    api_key  => '123456789012345',
    auto_api => 1,
    cache    => Cache::FileCache->new({
                    namespace          => 'wundercache',
                    default_expires_in => 2400 }),
);

# print header
printf "%-10s%-4s%-4s%-8s%-20s\n",
       'Time',
       "\x{2109}",
       "\x{2103}",
       'Rain %',
       'Conditions';

# print hourly
for (@{ $w->hourly })
{
    printf "%8s%4i%4i%8i  %-30s\n",
           $_->{FCTTIME}{civil},
           $_->{temp}{english},
           $_->{temp}{metric},
           $_->{pop},
           $_->{condition};
}

代码没有太多变化。添加了use Cache::FileCache;这行代码导入模块,并在Wunderground API调用中添加了一个cache参数。WWW::Wunderground::API足够智能,不会为不同的位置返回缓存的结果。

结论

这可能已经足够开始使用了,但是还有更多可以对这个脚本做的事情。我可以通过使用环境变量而不是API密钥和默认位置的硬编码值来使脚本更具可移植性。异常处理可以更好——在运行脚本之前检查互联网连接,更优雅地处理失败的API调用(例如,对于未知的位置)。最后,为什么让用户输入位置呢?我们可以使用用户的IP地址,然后使用Geo::IP模块进行地理定位。

Wunderground API不仅提供24小时预报,还有更多功能。查看他们的API文档

封面图片© NASA Goddard Space Flight Center


本文最初发布在PerlTricks.com

标签

David Farrell

David是一位专业程序员,经常在Twitter博客上分享代码和编程艺术。

浏览他们的文章

反馈

这篇文章有问题吗?请在GitHub上打开一个issue或pull request帮助我们。