このすみノート

Webエンジニアが技術や趣味を書くブログです。

Perlを復習しながら、HTTP(S)クライアントとJSONパースからのCSVファイル出力を書いた

「退屈なことはPythonにやらせよう」的な作業があったのですが、せっかくなのでPerlでやることにしました。 なぜPerlを選んだのかと言うと、しばらくPerlから遠ざかっていたこともあり、久しぶりに書きたくなったからです。

やりたいことはWeb APIからJSONを取得して、それをCSVに変換してファイル出力するという内容です。

開発環境の事前準備

今回はスポット的に実行できれば良いので、Dockerを使うことにしました。

docker run -v $(pwd):/work -it --rm perl:5.30 /bin/bash

「-it /bin/bash」で起動したDockerコンテナーの中に入るので、そこから必要なCPANモジュールをインストールします。 私はcpanmを使っているのですが、cpanmはRebuild.fmの宮川達彦さんが開発していることでも有名です。

# JSONパースで使います
cpanm JSON
# HTTPクライアントとして使います
cpanm LWP::UserAgent
# LWP::UserAgentでHTTPS通信するために使います
cpanm LWP::Protocol::https
# CSV出力するために使います
cpanm Text::CSV_XS

CPANモジュールのインストールが終わったら、「cd /work」でホストとマウントしているディレクトリに移動します。 これで事前準備は完了です。

# 「-v $(pwd):/work」で、ホスト側のカレントディレクトリをコンテナーの/workにマウントしているため
cd /work
perl your_script.pl

HTTP(S)クライアントによる通信と、JSONパースからのCSV出力サンプル

今回のサンプル用に、適当に作ったJSONファイルをGitHub Gistに用意しました。

gist.github.com

作成したperlスクリプトを掲載します。 今回はPerlの復習も目的のひとつにあるので、簡単な解説も続けて記載します。

#!/usr/bin/perl

use strict;
use warnings;
use URI;
use LWP::UserAgent;
use Data::Dumper;
use JSON qw/from_json/;
use Text::CSV_XS;

use constant JSON_API => "https://gist.githubusercontent.com/konosumi/3e3662e46e8db9283c2ad4d650f69483/raw/f53b78e810d62dc24e5a0864056fc424da668094/blog-perl-lwp-csv-sample.json";
use constant SAVE_CSV_FILE => "./sample.csv";

# HTTPS通信でJSONファイルを取得する
my $ua = LWP::UserAgent->new;
my $url = URI->new(JSON_API);
my $res = $ua->get($url);
warn "取得したJSONファイルの内容を出力します";
warn $res->content;

# 取得したJSONをパースする
my $json = from_json( $res->content );
warn "パースしたJSONの中身を出力します";
warn Dumper $json;

# ファイルに書き込むためのCSV文字列を作成する
my $csv = Text::CSV_XS->new ({ binary => 1 });
$csv->combine((
    $json->{test}->{a},
    $json->{test}->{b},
    $json->{sample}
));
warn "次の内容をCSVファイルに書き込みます";
warn $csv->string;

# CSVをファイルに出力します
open(FH_CSV, '> ' . SAVE_CSV_FILE);
print FH_CSV $csv->string;
close(FH_CSV);

Perlの復習

use strict

use strict;

JavaSciptにはStrictモードがあり、ファイルの先頭に"use strict";と記述するとJSが厳格になります。

developer.mozilla.org

Perlにも似たような手法があり、よほどの事情がない限りはファイルの先頭に「use strict;」を記述します。

strictプラグマはPerlの文法チェックを厳しくするためのプラグマです。strictプラグマは、Perlのスクリプトを書くときには、必ず記述するようにしてください。
参考:https://tutorial.perlzemi.com/blog/20130912137895.html

use warnings

use warnings;

use warningsは警告出力において役立つため、use strictとセットで記述します。

Perlにおいては、デフォルトの状態では、警告は表示されず、スクリプトが実行されます。warningsプラグマを使えば、警告を表示させることができます。スクリプトを書く場合は、strictプラグマとあわせて、必ず記述するようにしましょう。
参考:https://tutorial.perlzemi.com/blog/20130916137930.html

定数の定義

use constant SAVE_CSV_FILE => "./sample.csv";

Perlでは、「use constant」を使って定数を定義します。

LWP::UserAgentによるHTTP(S)通信

LWP::UserAgentはPerlのHTTPクライアントで、私が新人WEBエンジニアのときにも使っていた、老舗のCPANモジュールです。 LWPの書き方は色々あるのですが、今回は明示的にURIを作成してから通信することにしました。

my $ua = LWP::UserAgent->new;
my $url = URI->new(JSON_API);
my $res = $ua->get($url);

JSONのパース

JSONモジュールがあるので、それを使います。 JSONクラスにはサブルーチンが色々あるのですが、今回は文字列からのJSONパースなので、from_jsonに限定してインポートしています。

use JSON qw/from_json/;

# 取得したJSONをパースする
my $json = from_json( $res->content );
warn "パースしたJSONの中身を出力します";
warn Dumper $json;

CSV文字列の作成

Text::CSV_XSを使います。

use Text::CSV_XS;

my $csv = Text::CSV_XS->new ({ binary => 1 });
$csv->combine((
    $json->{test}->{a},
    $json->{test}->{b},
    $json->{sample}
));
warn "次の内容をCSVファイルに書き込みます";
warn $csv->string;

今回はCSVを作成する例ですが、CSVの読み込みは「Perlプログラミング入門ゼミ」が参考になります。

tutorial.perlzemi.com

CSVのファイル出力

Perlでは、標準のファイルハンドルがファイル読み書きの基本形です。

# ファイルハンドルを開く
open(FH_CSV, '> ' . SAVE_CSV_FILE);
# print [ファイルハンドル] 文字列
print FH_CSV $csv->string;
# ファイルハンドルを閉じる
close(FH_CSV);

さいごに

しばらくPerlから遠ざかっていたこともあり、新鮮な気持ちで書けました。 一部忘れていた文法もあったのですが、意外と書いてるうちに思い出しました。

ちなみに私は今でもPerlが好きなのですが、理由は単純に変数宣言に「my」があるからです。 なぜと聞かれると困るのですが、「my」を使った変数宣言に、謎の愛着と親近感があります。

なお本記事の執筆では、一部「Perlプログラミング入門ゼミ」を参考にさせていただきました。 この場を借りて、御礼申し上げます。

tutorial.perlzemi.com