ここで長くなって申し訳ありませんが、私の問題の説明に加えて、私の小さな進歩を含めることは理にかなっていると思いました!
複数のテーブルを含むいくつかの html ページからデータを抽出したいと考えています。クリティカル テーブルは、 で使用されるスキームでは、 にありHTML::TableExtract
ますdepth=>0, count=>2
。ここのコード例で使用した特定のページはhttp://www.myschool.edu.au/ResultsInNumbers/Index/61209/ConingsbyStateSchool/46701/2011です。たとえば、「Coningsby」など、入力する場所の最初に迷惑な検索CAPTCHAがあります。周囲の HTML を無視すると、テーブル構造は基本的に以下のブロックに示すようになります。
<table class="results-in-numbers">
<thead>
<tr>
<td class="year-column"></td>
<th colspan="2" scope="col">Reading</th>
<th colspan="2" scope="col">Writing</th>
</tr>
</thead>
<tbody>
<tr class="selected-school-row">
<th scope="row" rowspan="3">Year 3</th>
<td colspan="2">
<span class="avg">449</span>
<span class="err">404 - 494</span>
</td>
<td colspan="2">
<span class="avg">395</span>
<span class="err">359 - 431</span>
</td>
</tr>
<tr class="color-row">
<td><img src="" alt ="" /></td>
<td><img src="" alt =""/></td>
<td><img src="" alt ="" /></td>
<td><img src="" alt =""/></td>
</tr>
<tr class="sim-all-row">
<td>
<span class="sim">SIM</span>
<span class="sim-avg">411</span>
<span class="err">402 - 420</span>
</td>
<td>
<span class="all">ALL</span>
<span class="sim-avg">416</span>
</td>
<td>
<span class="sim">SIM</span>
<span class="sim-avg">410</span>
<span class="err">402 - 418</span>
</td>
<td>
<span class="all">ALL</span>
<span class="sim-avg">416</span>
</td>
</tr>
</tbody>
</table>
いくつかの方法で表を単純化しました。まず、実際には、Reading と Writing だけでなく、上部に 5 つの全体的な見出しがありますが、削除された各複製のレイアウトは Reading と Writing のレイアウトとまったく同じです。次に、行に示すように、「Year 3」に対応する行のトリプレットを 1 つだけ含めました <th scope="row" rowspan="3">Year 3</th>
。私の質問にとって重要なことは、そのような行スパンがいくつあるかわからないという事実です。例のページでは 3 つですが、場合によっては 1 つしかなく、最大で 4 つです。
出力のデータを整理して、各年に関連する数字をコンマ区切り形式にする (「3 年目」のように 1 行で) ようにしたいので、年と年を検出できるようにする必要があります。次に、次の 2 つのテーブル行もキャプチャして、1 つのrowspan="3"
ブロックを表す 1 行の出力が読み取られるようにします。
3,449,404,494,395,359,431,411,402,420,416,410,402,418,416
先頭の 3 は「3 年目」を表します。3行のrowspan-edブロックを処理する賢明な方法を本当に知らないので、現在、私のコードは次のように行を生成するだけです(途中の不要な空白行を含む):
#!/usr/bin/perl
use HTML::TableExtract;
use constant false => 0;
use constant true => 1;
foreach $html_file (@ARGV) {
print "$html_file \n";
$te = HTML::TableExtract->new( gridmap => false, subtables => true );
$te->parse_file($html_file);
# I don't know how many rows there are in the table, so I don't
# know how to count through them in triplets
foreach my $r ( $te->table(0,2)->rows() ) {
foreach my $col ( @$r ) {
# remove unwanted white space that results from the multiple
# spans within each <td> </td> block
$col =~ s/[\h\v]+/ /g;
# remove leading whitespace
$col =~ s/^ *//;
# remove trailing whitespace
$col =~ s/ *$//;
print $col, " ";
}
print "\n";
}
print "\n";
}
GotSchools/61/61998-61209-ConingsbyStateSchool-46701-2011-n
Reading Writing
Year 3 449 404 - 494 395 359 - 431
SIM 411 402 - 420 ALL 416 SIM 410 402 - 418 ALL 416
進め方についてアドバイスをいただければ幸いです。たとえば、正規表現を使用して、行の先頭にある年を検出し、SIM と ALL という単語を削除する必要がありますか? また、ここで「402 - 418」のように表示されるエントリに、実際には「 - 」と表示される可能性のあるエントリのデータが欠落しているページもあります。これは、コンテンツを介在させずにカンマ区切りとして出力したいと考えています。
アドバイスをいただければ幸いです。