15 November 2010

(Perl) HTML内の表(table)をCSVに変換する

HTMLで管理している写真データを、CSVに変換するスクリプト

■ 対象とするHTMLファイル内の表(TABLE)の例


<table>
<tr><th>no.</th><th>photo</th><th>Caption</th></tr>
<tr>
<td>0001</td>
<td><a href="0001.jpg"><img src="t/0001.jpg"></a></td>
<td>Rose</td>
</tr>
<tr>
<td>0002</td>
<td><a href="0002.jpg"><img src="t/0002.jpg"></a></td>
<td>Cyclamen</td>
</tr>
</table>

■ ソースコード


#!/usr/bin/perl

use strict;
use warnings;

use pQuery;
use HTML::Scrubber;
use HTML::TagParser;
use Text::CSV_XS;

my $strInputFilename = "./test2.html";
my $strTemp = undef;
my @arrCsvRaw = (); # CSV_XSに渡すCSV作成用の配列

my $scrubber = HTML::Scrubber->new();
my $csv = Text::CSV_XS->new({binary=>1}); # 日本語の場合は binary を ON にする

pQuery($strInputFilename)->find("tr")->each( sub{
@arrCsvRaw = ();
pQuery($_)->find("td")->each( sub{
$strTemp = $_->innerHTML();
$strTemp =~ s/\x0D\x0A|\x0D|\x0A/<br \/>/g; # 改行の除去
$strTemp =~ s/\x09/\x20/g; # タブをスペースに変換
$strTemp =~ s/\x20+/\x20/g; # 連続したスペースの統合
if(length($scrubber->scrub($strTemp))>0){ push(@arrCsvRaw, $scrubber->scrub($strTemp)); }
else
{
if(length(GetAttribValue($strTemp, 'a', 'href'))>0){ push(@arrCsvRaw, GetAttribValue($strTemp, 'a', 'href')); }
elsif(length(GetAttribValue($strTemp, 'img', 'src'))>0){ push(@arrCsvRaw, GetAttribValue($strTemp, 'img', 'src')); }
else{ push(@arrCsvRaw, ""); }
}
});
$csv->combine(@arrCsvRaw);
print($csv->string()."\n");
});

print("end script\n");

exit();


#
# 引数:$strHTML, $strTagName, $strElementName
# 引数の例: '<img src="x.jpg">', 'img', 'src'
# 戻り値:$str(値が見つからないときは長さゼロの文字列)
# 戻り値の例:'x.jpg'
sub GetAttribValue
{
my $html = HTML::TagParser->new();

$html->parse("<html><body>".$_[0]."</body></html>");
my $elem = $html->getElementsByTagName($_[1]);
my $strValue = $elem->getAttribute($_[2]) if ref $elem;

return($strValue) if defined $strValue;
return("");
}

■ 出力例


0001,0001.jpg,"Rose"
0002,0002.jpg,"Cyclamen"

■ 2010年11月16日 追記

配列 @arrCsvRaw の初期化に undef を代入していたが、これでは初期化出来ない。

@arrCsvRaw = undef;

@arrCsvRaw = ();

のように、空の配列を代入して初期化する。 本文のソースコードは修正済み