1

HTML::TreeBuilder を使用して不動産の Web ページを解析しており、次のコードがあります。

$values{"Pcity"} = $address->look_down("_tag" => "span", 
                   "itemprop" => "addressLocality")->as_text;
$values{"PState"} = $address->look_down("_tag" => "span", 
                   "itemprop" => "addressRegion")->as_text;

一部のページには都市または州が含まれておらず、パーサーはエラーで終了します。

Can't call method "as_text" on an undefined value

それを修正するために、次の方法を使用しました。

$values{"Pcity"} = $address->look_down("_tag" => "span", 
                   "itemprop" => "addressLocality");
if(defined($values{"Pcity"}))
{
    $values{"Pcity"} = $values{"Pcity"}->as_text;
}
else
{
    $values{"Pcity"} = '';
}

それは機能しますが、今では 1 行ではなく 9 行になっています。このような場所がたくさんあるので、コードはかなり大きくなります。

最適化する方法はありますか?

4

2 に答える 2

2

属性に指定された値のいずれかを持つ$address複数が決して含まれないと仮定すると、次のように書くことができます<span>itemprop

for my $span ( $address->look_down(_tag => 'span') ) {
   my $itemprop    = $span->attr('itemprop');
   $values{Pcity}  = $span->as_text if $itemprop eq 'addressLocality';
   $values{PState} = $span->as_text if $itemprop eq 'addressRegion';
}

しかし、HTML ツリーへのアクセスは、 を使用することではるかに簡単にHTML::TreeBuilder::XPathなり、不器用な の代わりに XPath 式を使用して構造にインデックスを付けることができますlook_down。それを使用したソリューションは次のようになりますが、ただし、存在しないノードに対しては;ではなくfindvalue空の文字列を返します。しかし、それはまだfalseと評価されるので、あなたにとってはうまくいくはずです。''undef

use strict;
use warnings;

use HTML::TreeBuilder::XPath;

my $xp = HTML::TreeBuilder::XPath->new_from_file(*DATA);

my %values;

$values{Pcity}  = $xp->findvalue('//span[@itemprop="addressLocality"]');
$values{PState} = $xp->findvalue('//span[@itemprop="addressRegion"]');

use Data::Dump;
dd \%values;

__DATA__
<html>
<head>
  <title>Title</title>
</head>
<body>
  <span itemprop="addressLocality">My Locality</span>
  <span itemprop="addressRegion">My Region</span>
</body>
</html>

出力

{ Pcity => "My Locality", PState => "My Region" }
于 2014-09-06T22:51:00.783 に答える