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 = ();

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