2014-09-06 4 views
1

Я разборе веб-страницу недвижимости, используя HTML :: TreeBuilder, и имеют следующий код:HTML :: Tree: Не удается вызвать метод «as_text» на неопределенное значение

$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. И поскольку у меня много таких мест, код станет значительно больше.

Есть ли способ для оптимизации?

ответ

1

Это короче:

$a = $address->look_down("_tag" => "span", "itemprop" => "addressLocality"); 
$values{"Pcity"} = $a ? $a->as_text : ''; 
+0

Это может быть написано '$ значения {Pcity} = $ а && $ a-> as_text' с минимальной разницей, что' $ значения {Pcity} 'заканчивается как 'undef' вместо пустой строки, если элемент span не найден. Но учтите, что вы никогда не должны использовать ни '' $ a', ни '$ b' нигде, кроме блока блока' sort', поскольку эти идентификаторы зарезервированы. – Borodin

+0

в этом примере использование $ a не имеет побочных эффектов –

+0

'' '' '' '' '' '' '' следует избегать, как само собой разумеющееся, так же, как всегда должны быть прагма 'strict' и' warnings' включены, даже если они не имеют никакого значения для данной программы. Нечего сказать, что модификация не может добавить вызов 'sort' и ввести неясные ошибки. В этом случае вы не знаете, содержит ли код OP 'sort'. Кроме того, '$ a' бесполезен как идентификатор, поскольку он не имеет смысла. – Borodin

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 возвращает пустую строку '' для несуществующих узлов, а не undef; но это должно работать для вас, поскольку оно по-прежнему оценивается до false.

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" } 

 Смежные вопросы

  • Нет связанных вопросов^_^