Featured image of post 第1回-PerlでHTTP API入門 - 最初の一歩は簡単だった

第1回-PerlでHTTP API入門 - 最初の一歩は簡単だった

Perl HTTP::TinyでAPI統合の基礎を学ぶ。OpenWeatherMap APIを使い、JSON解析・エラーハンドリングを実装。初心者向けに丁寧に解説します。

はじめに

皆さん、Perlで外部APIを使ったことはありますか?今回から新シリーズ「Perl API統合パターン」を開始します。

このシリーズでは、天気予報APIを題材に、複数のAPIサービスを統合して扱うための設計パターンを学んでいきます。Perl入学式を卒業し、Mooの基礎を学んだ皆さんが、次のステップとして実践的なAPI連携スキルを身につけることを目標としています。

対象読者

  • Perl入学式を卒業したばかりの方
  • 「Mooで覚えるオブジェクト指向プログラミング」シリーズを読了済みの方
  • Perl v5.36以降の環境を使用できる方
  • 外部APIを使ったプログラムに興味がある方

このシリーズで学ぶこと

全8回を通じて、以下のスキルを身につけます。

  • HTTP::TinyとJSON::PPを使ったAPI連携の基礎
  • 異なるインターフェースを持つAPIサービスの統合方法
  • 複数のAPIを統一的に扱うための設計パターン
  • キャッシュ戦略とエラーハンドリングの実践

今回の目標

第1回となる今回は、天気予報API(OpenWeatherMap)を直接叩く素朴なコードを作成します。まずはシンプルに「動くコード」を書いて、APIの基本的な使い方を学びましょう。

天気予報APIの呼び出し

外部APIを呼び出すには、HTTPリクエストを送信し、レスポンス(通常はJSON形式)を解析する必要があります。Perlでは標準モジュールのHTTP::TinyとJSON::PPを使うことで、追加のインストールなしにAPI連携が可能です。

基本的なAPIリクエスト

まず、シンプルなAPIリクエストのコードを見てみましょう。今回はAPIキーなしで動作するモックデータを使用します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/usr/bin/env perl
use v5.36;
use HTTP::Tiny;
use JSON::PP qw(encode_json decode_json);

# APIリクエストを送信
my $http = HTTP::Tiny->new;
my $url  = 'https://api.example.com/weather?city=Tokyo';

# 実際のAPIの代わりにモックデータを使用
my $response = {
    success => 1,
    content => encode_json({
        city        => 'Tokyo',
        temperature => 25.5,
        condition   => 'sunny',
        humidity    => 60,
    }),
};

# レスポンスを解析
if ($response->{success}) {
    my $data = decode_json($response->{content});
    say "都市: $data->{city}";
    say "気温: $data->{temperature}℃";
    say "天気: $data->{condition}";
    say "湿度: $data->{humidity}%";
}

HTTP::Tinyの基本

HTTP::TinyはPerlに標準で含まれる軽量なHTTPクライアントです。

  • get($url) - GETリクエストを送信
  • post($url, $options) - POSTリクエストを送信
  • レスポンスはハッシュリファレンスで返される

JSON::PPの基本

JSON::PPはJSON形式のデータを扱うための標準モジュールです。qw(encode_json decode_json)でインポートして使用します。

  • decode_json($json_string) - JSON文字列をPerlのデータ構造に変換
  • encode_json($perl_data) - Perlのデータ構造をJSON文字列に変換

OpenWeatherMap APIを使う

実際の天気予報APIとして、OpenWeatherMapを例に見てみましょう。このサービスは無料プランで月1000回までAPIを利用できます。

APIの仕様

OpenWeatherMapの現在の天気情報APIは以下の形式です。

  • エンドポイント: https://api.openweathermap.org/data/2.5/weather
  • パラメータ:
    • q - 都市名(例: Tokyo,JP)
    • appid - APIキー
    • units - 単位(metric で摂氏)
    • lang - 言語(ja で日本語)

実装コード

以下は、OpenWeatherMap APIを呼び出す基本的なコードです。今回はモックレスポンスを使用して、APIキーなしで動作するようにしています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#!/usr/bin/env perl
use v5.36;
use HTTP::Tiny;
use JSON::PP;

# OpenWeatherMap API(モック版)
sub get_weather_from_openweathermap ($city) {
    # 実際のAPIレスポンスを模したモックデータ
    my %mock_data = (
        'Tokyo' => {
            name => 'Tokyo',
            main => {
                temp     => 25.5,
                humidity => 60,
            },
            weather => [
                { description => '晴れ' },
            ],
        },
        'Osaka' => {
            name => 'Osaka',
            main => {
                temp     => 27.2,
                humidity => 65,
            },
            weather => [
                { description => '曇り' },
            ],
        },
        'Sapporo' => {
            name => 'Sapporo',
            main => {
                temp     => 18.3,
                humidity => 70,
            },
            weather => [
                { description => '雨' },
            ],
        },
    );

    return $mock_data{$city};
}

# メイン処理
my @cities = qw(Tokyo Osaka Sapporo);

say "=== OpenWeatherMap 天気情報 ===";
for my $city (@cities) {
    my $data = get_weather_from_openweathermap($city);
    if ($data) {
        my $temp        = $data->{main}{temp};
        my $humidity    = $data->{main}{humidity};
        my $description = $data->{weather}[0]{description};
        say "$city: $description(気温 $temp℃、湿度 $humidity%)";
    }
    else {
        say "$city: データなし";
    }
}

実行結果:

1
2
3
4
=== OpenWeatherMap 天気情報 ===
Tokyo: 晴れ(気温 25.5℃、湿度 60%)
Osaka: 曇り(気温 27.2℃、湿度 65%)
Sapporo: 雨(気温 18.3℃、湿度 70%)

OpenWeatherMap APIのレスポンス構造

実際のOpenWeatherMap APIは以下のようなJSON形式でデータを返します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
{
  "name": "Tokyo",
  "main": {
    "temp": 25.5,
    "humidity": 60,
    "pressure": 1013
  },
  "weather": [
    {
      "main": "Clear",
      "description": "晴れ"
    }
  ],
  "wind": {
    "speed": 3.5
  }
}

この構造を理解しておくと、必要なデータを正確に取り出すことができます。

  • name - 都市名
  • main.temp - 気温(摂氏、units=metricの場合)
  • main.humidity - 湿度(%)
  • weather[0].description - 天気の説明
  • wind.speed - 風速(m/s)

今回の完成コード

今回作成した完成コードを以下に示します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#!/usr/bin/env perl
use v5.36;
use HTTP::Tiny;
use JSON::PP;

# OpenWeatherMap API呼び出し(モック版)
# 実際にAPIを使う場合は、HTTP::Tiny->get() でリクエストを送信
sub get_weather_from_openweathermap ($city) {
    # モックデータ(実際のAPIレスポンスを模した構造)
    my %mock_data = (
        'Tokyo' => {
            name => 'Tokyo',
            main => {
                temp     => 25.5,
                humidity => 60,
            },
            weather => [
                { description => '晴れ' },
            ],
        },
        'Osaka' => {
            name => 'Osaka',
            main => {
                temp     => 27.2,
                humidity => 65,
            },
            weather => [
                { description => '曇り' },
            ],
        },
        'Sapporo' => {
            name => 'Sapporo',
            main => {
                temp     => 18.3,
                humidity => 70,
            },
            weather => [
                { description => '雨' },
            ],
        },
    );

    return $mock_data{$city};
}

# 天気情報を整形して表示
sub show_weather ($city) {
    my $data = get_weather_from_openweathermap($city);
    
    if ($data) {
        my $temp        = $data->{main}{temp};
        my $humidity    = $data->{main}{humidity};
        my $description = $data->{weather}[0]{description};
        say "$city: $description(気温 $temp℃、湿度 $humidity%)";
    }
    else {
        say "$city: データを取得できませんでした";
    }
}

# メイン処理
say "=== 天気予報アグリゲーター ===";
say "";

my @cities = qw(Tokyo Osaka Sapporo Fukuoka);

for my $city (@cities) {
    show_weather($city);
}

実行結果:

1
2
3
4
5
6
=== 天気予報アグリゲーター ===

Tokyo: 晴れ(気温 25.5℃、湿度 60%)
Osaka: 曇り(気温 27.2℃、湿度 65%)
Sapporo: 雨(気温 18.3℃、湿度 70%)
Fukuoka: データを取得できませんでした

まとめ

今回は、天気予報APIを直接叩くシンプルなコードを作成しました。

  • HTTP::TinyでHTTPリクエストを送信する方法を学んだ
  • JSON::PPでJSONレスポンスを解析する方法を学んだ
  • OpenWeatherMap APIのレスポンス構造を理解した

この段階では、すべてが順調に動いています。1つのAPIだけを使う分には、このシンプルなコードで十分です。

次回予告

次回は、別の天気情報サービス(WeatherStack API)を追加します。2つのAPIは温度の単位やレスポンス構造が異なります。両方を同時に使おうとすると、どのような問題が発生するのでしょうか?お楽しみに!

comments powered by Disqus
Hugo で構築されています。
テーマ StackJimmy によって設計されています。