読者です 読者をやめる 読者になる 読者になる

ITの隊長のブログ

ITの隊長のブログです。いや、まだ隊長と呼べるほどには至っていないけど、日々がんばります。CakePHPとPlayFrameworkを使って仕事しています。最近はAngular2をさわりはじめたお(^ω^ = ^ω^)

Perlでxmlパーサーを作ってみったった。

Perl

スポンサードリンク

f:id:aipacommander:20141009102647j:plain
そろそろ浮気せずに言語を極めるべきでは・・・?
と、最近悩み始めた隊長です。


でもでもね。一度試した言語で同じことをするなんて
個人的にはあんまりおもしろくない(>< )


ってなわけで、最近は
Java -> Python -> PHP
と、パーサー&スクレイピングを組んできて
今度はPerlなわけですよ。


実はPerlは初めてではありません。なんどか組んだことがあります。
深くは組んだことはありませんが、面白いですよね。この言語も


当時組んだときにはほとんど覚えてはいませんが
リファレンスとスカラーの使い方。特殊変数の多さに
苦しめられた覚えがあります。


Perlは書き方が色々ありすぎて、読み辛いっちゃ読み辛い。
しかし慣れてくるとそれがメリットだったりします。
個人的には好きです。Perl


しかしまぁ、ほとんど正規表現でしか使っていませんけどね。
あとはLinuxでのワンライナーとか。


と、前置きはさておいて
こういった理由でPerlを使って、今回Xmlパーサーを組んでみました。


その時の内容をメモ

Xmlをパースするのに必要なモジュールがインストールされているか確認する


おっと
ちょっとその前に事前情報


環境は「CentOS5」以上を想定しています。


Xmlをパースするにあたり必要なモジュールとして

  • XML::Simple(Xmlパーサー)
  • LWP(wwwアクセスに必要なモジュール)


以上の2つをインストールします。


ちなみに、事前にインストールされているか、確認するコマンド

# LWPがインストールされているか確認ワンライナー
$ perl -MLWP -le "print(LWP->VERSION)"

# XML::Simpleがインストールされているか確認ワンライナー
$ perl -MXML::Simple -le "print(XML::Simple->VERSION)"


上記確認ワンライナーをタイプしていみて
下記のようにバージョンがでてこればインストールされています。

$ perl -MLWP -le "print(LWP->VERSION)"
6.04

$ perl -MXML::Simple -le "print(XML::Simple->VERSION)"
2.20


今回はインストールされていないことを想定してインストールしましょう。


LWPはcpanでインストールしましょう。

$ perl -MCPAN -eshel

cpan> install Bundle::LWP
cpan> quitl

XML::Simpleについては、yumコマンドでインストールしましょう。

yum install perl-XML-Simple
perl -MXML::Simple -le "print(XML::Simple->VERSION)"


これで、確認ワンライナーをタイプして、バージョンが表示されれば
準備完了となります。


パーサーを組んでみて、テストする。


LWPをインストールしましたが、今回の例では使いません(´・ω・)
予め用意しているXMLファイルを使って例を記述します。


でも、念のためLWPを使った場合の例も
コメントアウトで記述しておきますb


それでは簡易パーサーを組んでみて、テストしてみましょう。

#!/usr/bin/perl

# モジュールをインポート
use Data::Dumper;
use LWP;
use XML::Simple;

# LWPを使った場合、今回は使わないのでコメントアウト
# urlにリクエスト -> レスポンス取得
=pod
my $url = "http://www.exapmle.com/sitemap.xml";
my $uri = URI->new($url);
my $req = GET($uri);
# UserAgentを使うなら追加
my $ua = LWP::UserAgent->new;
# これがレスポンスデータ、Xmlデータとなる
my $xmlData = $ua->request($req);
=cut

# 簡易的なXmlデータの用意
my $xmlData =<<EOF;
<?xml version="1.0" encoding="UTF-8"?>
<root>
	<url>
		<loc>http://www.example.com/</loc>
		<lastmod>2013-03-07</lastmod>
		<changefreq>daily</changefreq>
		<priority>1.0</priority>
	</url>
	<url>
		<loc>http://www.example2.com/</loc>
		<lastmod>2013-03-08</lastmod>
		<changefreq>daily</changefreq>
		<priority>1.1</priority>
	</url>
</root>
EOF

# Xml::Simpleのインスタンス生成
my $xml = XML::Simple->new;

# xmlを読み込ませる
my $data = $xml->XMLin($xmlData);
# LWPを使った場合はこうなる
# my $data = $xml->XMLin($xmlData->content);


ここまでXML::Sipmleを使う準備はおk
確認していきましょう

構造をダンプして確認する
print Dumper $data;

結果

$VAR1 = {
          'url' => [
                   {
                     'priority' => '1.0',
                     'lastmod' => '2013-03-07',
                     'loc' => 'http://www.example.com/',
                     'changefreq' => 'daily'
                   },
                   {
                     'priority' => '1.1',
                     'lastmod' => '2013-03-08',
                     'loc' => 'http://www.example2.com/',
                     'changefreq' => 'daily'
                   }
                 ]
        };


とまあ、こういった構造になります。
続けていきましょう。

配列の[0]にアクセス
print Dumper $data->{'url'}[0];


結果

$VAR1 = {
          'priority' => '1.0',
          'lastmod' => '2013-03-07',
          'loc' => 'http://www.example.com/',
          'changefreq' => 'daily'
        };


ここからは、Hashの構造になります。

print Dumper $data->{'url'}[0]->{'loc'};


結果

$VAR1 = 'http://www.example.com/';


と、なる。

複数タグをループさせる

<url>のタグは現在、2つ存在しています。
また、その下は配列として構造化されていますので
ループさせることが可能です。


foreachを使ってやってみましょう。

foreach my $urlTag(@{$data->{'url'}}) {
	print $urlTag->{'lastmod'}."\n";
	print $urlTag->{'loc'}."\n";
}


結果

2013-03-07
http://www.example.com/
2013-03-08
http://www.example2.com/


複数のタグがある場合はこんな感じで
ループさせることができます。

まとめ


他にもオプションやら色々用意されていますが
次機会があれば、やります。


perlも結構ええなぁ。。。
そろそろ本命を決めないとやばい。