2009-11-07 9 views
5

Odkąd zapytałem się, jak parsować html z regex i zostało nieco roztrzaskane (słusznie), studiowałem moduły Perl: HTML::TreeBuilder, HTML::Parser, HTML::TokeParser i HTML::Elements.Jak mogę znaleźć zawartość elementu div przy użyciu modułów HTML Perla, jeśli znam wewnątrz niego znacznik?

Mam HTML tak:

<div id="listSubtitlesFilm"> 
    <dt id="a1"> 
    <a href="/45/subtitles-67624.aspx"> 
     .45 (2006) 
    </a> 
    </dt> 
</div> 

chcę analizować zewnątrz /45/subtitles-67624.asp, ale co ważniejsze Chcę umieć analizować na zawartość div.

Dostałam ten przykład na poprzednie pytanie:

while (my $anchor = $parser->get_tag('a')) { 
    if (my $href = $anchor->get_attr('href')) { 
#http://subscene.com/english/Sit-Down-Shut-Up-First-Season/subtitles-272112.aspx 
     push @dnldLinks, $1 if $href =~ m!/subtitle-(\d{2,8})\.aspx!; 
    } 

To działało idealnie do tego, ale kiedy próbowałem go edytować trochę i używać go na `` div` to nie działa . Oto kod próbowałem:

Próbowałem za pomocą tego kodu:

while (my $anchor = $p->get_tag("dt")) { 
    if($stuff = $anchor->get_attr('a1')) { 
    print $stuff."\n"; 
    } 
} 
+0

przykro! zaktualizowałem to! – Codygman

+1

Jakiego modułu używasz? Wspomniałeś jak pięć w pytaniu, nie ma czegoś takiego jak HTML :: TreeParser, a twój kod nie wygląda tak, jak w HTML :: TreeBuilder ... – hobbs

+0

Używam HTML :: TokeParser :: Simple .. przepraszam za zamieszanie – Codygman

Odpowiedz

5

do adresu swoje konkretne pytanie, biorąc pod uwagę HTML:

<div id="listSubtitlesFilm"> 
    <dt id="a1"> 
    <a href="/45/subtitles-67624.aspx"> 
     .45 (2006) 
    </a> 
    </dt> 
</div> 

jestem zakładając, że jesteś zainteresowany w anchor text, tj ".45 (2006)", w tym przypadku, ale tylko wtedy, gdy kotwica występuje w a div o identyfikatorze listSubtitlesFilm.

#!/usr/bin/perl 

use strict; 
use warnings; 

use HTML::TokeParser::Simple; 

my $parser = HTML::TokeParser::Simple->new(handle => \*DATA); 

my @dnldLinks; 

while (my $div = $parser->get_tag('div')) { 
    my $id = $div->get_attr('id'); 
    next unless defined($id) and $id eq 'listSubtitlesFilm'; 

    my $anchor = $parser->get_tag('a'); 
    my $href = $anchor->get_attr('href'); 
    next unless defined($href) 
     and $href =~ m!/subtitles-(\d{2,8})\.aspx\z!; 
    push @dnldLinks, [$parser->get_trimmed_text('/a'), $1]; 
} 

use Data::Dumper; 
print Dumper \@dnldLinks; 


__DATA__ 
<div id="listSubtitlesFilm"> 
    <dt id="a1"> 
    <a href="/45/subtitles-67624.aspx"> 
     .45 (2006) 
    </a> 
    </dt> 
</div> 

wyjściowa:

 
$VAR1 = [ 
      [ 
      '.45 (2006)', 
      '67624' 
      ] 
     ]; 
+0

Dziękuję Tyle za szczegółowe wyjaśnienie Sinan! Twoja miłość do mnie! : P – Codygman

1

get_attr('a1') powinien mieć prawdopodobnie czytać get_attr('id') i byłoby wydrukować „a1”

myślę coraz zawartość tekst będzie wyglądać :

while (my $anchor = $parser->get_tag('div')) { 
    my $content = $parser-get_text('/div'); 
} 

Lub jeśli oznaczało zawartość tekstową link byłoby:

while (my $anchor = $parser->get_tag('a')) { 
    if (my $href = $anchor->get_attr('href')) { 
     my $content = $parser->get_text('/a'); 
#http://subscene.com/english/Sit-Down-Shut-Up-First-Season/subtitle-272112.aspx 
     push @dnldLinks, $1 if $href =~ m!/subtitle-(\d{2,8})\.aspx!; 
    } 
+0

Dziękuję, że pomogło, druga część pytania brzmi: jak zdobyć tekst między

GETTHISCONTENT
. Czy możesz w tym pomóc? Dzięki! – Codygman

+1

Dzięki za pomoc, przepraszam za zamieszanie, chyba mniej znaczy więcej tutaj. Moim ogólnym celem jest uzyskanie linku href z tagów

w tym określonym kontenerze div. – Codygman

1

Należy zmienić tutaj get_attr("a1") na get_attr("id"). get_attr (x) szuka atrybutu o nazwie x, ale podajesz mu wartość atrybutu, a nie jego nazwę.

Nawiasem mówiąc, znacznik <dt> nie jest <div>, jest tagiem pozycji dla <dl> (lista definicji).

4

Code używając HTML::TreeBuilder:

use HTML::TreeBuilder; 

my $tree = HTML::TreeBuilder->new_from_content($html); 

for my $link ($tree->look_down(
    _tag => 'a', 
    href => qr{/subtitle-\d{2,8}\.aspx}) 
) { 
    my $linkid = $link->attr('href') =~ m!/subtitle-\d{2,8}\.aspx!; 
    # Scalar context gets the first, and the first is the nearest parent 
    my $parent_div = $link->look_up(_tag => 'div'); 
    # Now the interesting bit of the link is in $linkid, the parent div ID 
    # is $parent_div->id or $parent_div->attr_id, and its text is e.g. 
    # $parent_div->as_trimmed_text or you can do other stuff with its content. 
} 
+0

Chciałbym móc głosować! :) Dzięki, staram się nie przeszkadzać wam zbytnio, ale po godzinie próbowania zorientowania się, byłem tak sfrustrowany! – Codygman

+0

Różne podklasy parserów są dobre dla różnych rodzajów pracy. TokeParser jest jednym z najprostszych i najszybszych, ale kiedy chcesz przejść w górę i w dół w strukturze tagów, TreeBuilder powinien być w twoim umyśle. – hobbs

+1

I jestem zdecydowanie * nie * błagam o głosy, ale teraz masz 21 przedstawicieli i możesz mnie upomnieć, jeśli tak zechcesz, i powinieneś "zaakceptować" jedną z odpowiedzi na twoje pytanie, jeśli jesteś zadowolony. – hobbs

5

Można użyć (kolejny moduł!) HTML::TreeBuilder::XPath, który, zgodnie z jego nazwą, pozwoli na korzystanie z XPath na obiektach HTML :: TreeBuilder.

#!/usr/bin/perl 

use strict; 
use warnings; 

use HTML::TreeBuilder::XPath; 

my $root = HTML::TreeBuilder::XPath->new_from_file("my.html"); 

# print $root->as_HTML; # useful to see how HTML::TreeBuilder 
# understands your HTML. For example it will wrap the implied 
# dl element around dt, which you need to take into account 
# when writing the XPath query below 

my $id= "a1"; 
# you need the .//dt because of the extra dl 
my @divs= $root->findnodes(qq{//div[.//dt[\@id="$id"]]}); 

print $divs[0]->as_HTML; # or as_text 
+0

Dzięki Mirod, użycie xpath wygląda na to, że naprawdę pomoże to RAD :) Komentarze również były bardzo pomocne, wiedząc, jak to rozumie mój HTML jest bardzo ważny. – Codygman

Powiązane problemy