2009-11-07 5 views
5

Seit ich gefragt habe, wie man html mit Regex parsen und ein bisschen zerschlagen wird (zu Recht), habe ich HTML::TreeBuilder, , HTML::TokeParser und HTML::Elements Perl-Module studiert.Wie kann ich den Inhalt eines div mit Perls HTML-Modulen finden, wenn ich ein Tag darin kenne?

Ich habe HTML wie folgt aus:

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

ich die /45/subtitles-67624.asp analysieren wollen, aber noch wichtiger ist Ich möchte wissen, wie Sie den Inhalt des div parsen.

ich dieses Beispiel auf einer früheren Frage gegeben wurde:

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!; 
    } 

Das perfekt dafür gearbeitet, aber wenn ich es ein wenig zu bearbeiten versucht und es auf ein verwenden `` div` es nicht funktioniert . Hier ist der Code, den ich versucht:

ich diesen Code versucht, mit:

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

Entschuldigung! aktualisiert es! – Codygman

+1

Welches Modul verwenden Sie eigentlich? Sie erwähnen wie fünf in Ihrer Frage, es gibt nicht so etwas wie HTML :: TreeParser, und Ihr Code sieht nicht so aus wie für HTML :: TreeBuilder ... – hobbs

+0

Ich benutze HTML :: TokeParser :: Simple .. Entschuldigung für die Verwirrung – Codygman

Antwort

5

zu adressieren, Ihre Frage, da die HTML:

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

ich Sie sind in dem Anchor-Text interessiert gehe davon aus, dh ".45 (2006)", in diesem Fall jedoch nur, wenn der Anker tritt in a div mit ID 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> 

Ausgang:

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

Vielen Dank für die detaillierte Erklärung Sinan! Du bringst mich dazu, Perl zu lieben! : P – Codygman

1

get_attr('a1') sollte wohl gelesen haben get_attr('id') und es würde drucken „a1“

Ich denke immer der Textinhalt aussehen würde, :

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

Oder wenn Sie den Textinhalt der Verbindung gemeint, wäre es:

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

Danke, das half, der andere Teil der Frage ist, wie man den Text von whats zwischen

GETTHISCONTENT
bekommen. Können Sie dabei helfen? Vielen Dank! – Codygman

+1

Danke für die Hilfe, Entschuldigung für die Verwirrung, ich denke, weniger ist mehr hier. Mein übergeordnetes Ziel ist es, die a href-Verbindung aus den Tags

in diesem angegebenen div-Container zu erhalten. – Codygman

1

Sie müssen die get_attr("a1") zu get_attr("id") hier ändern. Die get_attr (x) sucht nach einem Attribut mit dem Namen x, aber Sie geben es den Wert des Attributs, nicht seinen Namen.

übrigens der <dt>-Tag ist keine <div>, es ist der Element-Tag für eine <dl> (Definitionsliste).

4

-Code HTML::TreeBuilder mit:

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

Ich wünschte, ich könnte abstimmen! :) Danke, ich versuche, euch nicht zu sehr zu stören, aber nach einer Stunde des Versuchs, das herauszufinden, war ich so frustriert! – Codygman

+0

Die verschiedenen Parser-Unterklassen sind alle für verschiedene Arten von Arbeit gut. TokeParser ist einer der einfachsten und schnellsten, aber wenn Sie sich in der Tag-Struktur nach oben und unten bewegen möchten, sollte TreeBuilder im Hinterkopf sein. – hobbs

+1

Und ich bin nachdrücklich * nicht * betteln um Stimmen, aber Sie haben jetzt 21 rep und können mich aufheben, wenn Sie dies wünschen, und Sie sollten auch eine der Antworten auf Ihre Frage "akzeptieren", wenn Sie zufrieden sind. – hobbs

5

Sie (noch ein weiteres Modul!) Verwenden könnte HTML::TreeBuilder::XPath, die, wie pro seinen Namen, Sie XPath lassen verwenden, um auf HTML :: TreeBuilder Objekte.

#!/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

Danke mirod, mit xpath scheint es wird wirklich helfen, meine RAD :) Die Kommentare waren auch sehr hilfreich, zu wissen, wie es meine HTML versteht, ist sehr wichtig. – Codygman