2010-09-13 5 views
1

Je suis assez nouveau pour Perl/HTML. Voici ce que j'essaie de faire avec WWW::Mechanize et HTML::TreeBuilder:extrait tous les liens d'une page HTML, exclut les liens d'une table spécifique

Pour chaque page d'élément chimique sur Wikipedia, je dois extraire tous les hyperliens qui pointent vers les pages des autres éléments chimiques sur le wiki et imprimer chaque paire unique dans ce Format:

Atomic_Number1 (Chemical Element Title1) -> Atomic_Number2 (Chemical Element Title2) 

le seul problème est qu'il ya un mini tableau périodique sur la page de chaque élément chimique (en haut à droite de la page). Donc, cette petite table périodique fera juste le même résultat pour chaque élément. J'ai du mal à extraire tous les liens de la page SAUF de cette même table.

[Note: Je ne regardais $elem == 6 (carbone) (@line 42) pour la facilité de mise au point.]


Voici mon code:

#!/usr/bin/perl -w 

use strict; 
use warnings; 
use WWW::Mechanize; 
use HTML::TreeBuilder; 
my $mech = WWW::Mechanize->new(autocheck => 1); 

$mech = WWW::Mechanize->new(); 

my $table_url = "http://en.wikipedia.org/wiki/Periodic_table"; 

$mech->agent('Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_5; en-us)/
       AppleWebKit/533.17.8 (KHTML, like Gecko) Version/5.0.1 /
       Safari/533.17.8'); 

$mech->get($table_url); 

my $tree = HTML::TreeBuilder->new_from_content($mech->content); 
my %elem_set; 
my $atomic_num; 

## obtain a hash array of elements and corresponding titles and links 
foreach my $td ($tree->look_down(_tag => 'td')) { 

    # If there's no <a> in this <td>, then skip it: 
    my $a = $td->look_down(_tag => 'a') or next; 

    my $tdText = $td->as_text; 
    my $aText = $a->as_text; 

    if($tdText =~ m/^(\d+)\S+$/){ 
    if($1 <= 114){ #only investigate up to 114th element 
     $atomic_num = $1; 
    } 
    $elem_set{$atomic_num} = [$a->attr('title'), $a->attr('href')]; 
    } 
} 

## In each element's page. look for links to other elements in the set 
foreach my $elem (keys %elem_set) { 
    if($elem == 6){ 
    # reconstruct element url to ensure only fetch pages in English 
    my $elem_url = "http://en.wikipedia.org" . $elem_set{$elem}[1]; 
    $mech->get($elem_url); 

    ##################################################################### 
    ### need help here to exclude links from that mini periodic table ### 
    ##################################################################### 

    my @target_links = $mech->links(); 
    for my $link (@target_links) { 
     if($link->url =~ m/^\/(wiki)\/.+$/ && $link->text =~ m/^\w+$/){ 
     printf("%s, %s\n", $link->text, $link->url); 
     } 
    } 

    } 
} 

Répondre

2

utilisation WWW :: Méthode update_html de Mechanize pour supprimer cette table avant de trouver les liens. Cette méthode vous permet de faire ce que vous voulez au code source $mech->content.

+0

Merci! Mais il s'avère que la suppression de tableaux sur des pages wiki n'est pas une façon très précise, voire efficace, de réaliser ce que j'ai l'intention de faire, puisque les tableaux des pages wiki de chaque élément chimique ont des choses différentes dans leurs tags. Il est donc difficile de généraliser une fonction de suppression de table pour toutes les pages. En fait, j'ai fini par utiliser HTML :: TreeBuilder pour rechercher des liens dans

tags (puisque le type de liens que je cherche sont très probablement apparaître dans les paragraphes). Il a donné des résultats beaucoup plus précis et a couru assez rapidement. –

Questions connexes