【Perl】進捗を表示しながらダウンロードする


【Python 事始め】進捗を表示しながらダウンロードする」に続いて、Perl で同じことをやってみよう。Python の urllib モジュールに当たるのは、Perl では LWP::UserAgent モジュールだ1

LWP::UserAgent – search.cpan.org
http://search.cpan.org/~gaas/libwww-perl-5.834/lib/LWP/UserAgent.pm

ファイルのダウンロードには get メソッドを使う。構文は次のようになっている。

$ua->get( $url, %options )

%options に指定できるオプションは非常に多岐にわたっていて複雑だが、とりあえずは 2 つだけ覚えておけばいい。

:content_file
保存するファイル名
:content_cb
ブロックが読み出される度に呼び出される関数。引数としてブロックの中身と HTTP::Response オブジェクトが与えられる。

この 2 つのオプションはどちらか片方しか指定できない。つまり、進捗状況を表示するために :content_cb オプションを使うならば、ファイルの保存は自分でやらなければならないのだ。

スクリプトの例 download_test.pl

#!/usr/bin/perl
use strict;
use warnings;
use LWP::UserAgent;
use IO::File;
use URI;

# 標準出力をバッファリングしない
$|++;
# コマンドライン引数から URL を得る
my $url = URI->new( shift );
# URL からファイル名を得る
my $filename = ( split "/", $url->path )[ -1 ];
# ファイルを保存するためのファイルハンドル
my $fh = IO::File->new( $filename, "w" );
# 保存したバイト数
my $saved = 0;
# ダウンロード開始
LWP::UserAgent->new->get( $url, ":content_cb" => \&progress );
print "\n";

# ブロックが読み出される度に呼び出される関数
sub progress {
    my ( $content, $response ) = @_;
    # データの保存
    $fh->print( $content );
    $saved += length $content; 
    # 進捗の表示
    my $total_size = $response->content_length;
    my $percentage = $saved / $total_size * 100;
    printf "%.2f %% ( %d KB )\r",
        $percentage, $total_size / 1024;
}

実行例

$ perl download_test.pl "http://www.example.com/archive.zip"
12.34 % ( 567 KB )

  1. とはいえ、このモジュール自体はとてつもなく巨大で多機能だ。今回はそのうちファイルのダウンロード機能だけを使う。 

コメントを残す