2008-10-31 24 views
19

Previamente le pregunté cómo hacer esto en Groovy. Sin embargo, ahora estoy reescribiendo mi aplicación en Perl debido a todas las bibliotecas de CPAN.¿Cómo puedo extraer URL y vincular texto desde HTML en Perl?

Si la página contiene estos enlaces:

 
<a href="http://www.google.com">Google</a> 

<a href="http://www.apple.com">Apple</a> 

La salida sería:

 
Google, http://www.google.com 
Apple, http://www.apple.com 

¿Cuál es la mejor manera de hacer esto en Perl?

Respuesta

39

Para esto, consulte el uso del módulo WWW::Mechanize. Le buscará sus páginas web y luego le proporcionará fácil de trabajar con listas de URL.

my $mech = WWW::Mechanize->new(); 
$mech->get($some_url); 
my @links = $mech->links(); 
for my $link (@links) { 
    printf "%s, %s\n", $link->text, $link->url; 
} 

Bastante simple, y si usted está mirando para navegar a otras direcciones URL de esa página, que es aún más simple.

Mech es básicamente un navegador en un objeto.

+2

Me tomé la libertad de cambiar la declaración de impresión para incluir el texto del enlace, según lo solicitado por melling. – cjm

11

Eche un vistazo a HTML::LinkExtractor y HTML::LinkExtor, parte del paquete HTML::Parser.

HTML :: LinkExtractor es similar a HTML :: LinkExtor, excepto que además de obtener la URL, también obtiene el texto de enlace.

+1

Desafortunadamente, HTML :: LinkExtor no puede darle el texto dentro de la etiqueta , que dice que está interesado en él sólo se le informa del nombre de la etiqueta y sus atributos.. – cjm

+0

@cjm: Agregué un enlace a HTML :: LinkExtractor que produce el texto del enlace además de las URL. –

2

HTML es un lenguaje de marcado estructurado que se debe analizar para extraer su significado sin errores. El módulo Sherm enumerado analizará el HTML y extraerá los enlaces por usted. Las soluciones ad hoc basadas en expresiones regulares pueden ser aceptables si usted sabe que sus entradas siempre se formarán de la misma manera (no olvide los atributos), pero un analizador es casi siempre la respuesta correcta para procesar texto estructurado.

4

Sherm recomendado HTML::LinkExtor, que es casi lo que usted quiere. Lamentablemente, no puede devolver el texto dentro de la etiqueta < a>.

Andy recomendado WWW::Mechanize. Esa es probablemente la mejor solución.

Si encuentra que WWW :: Mechanize no es de su agrado, intente HTML::TreeBuilder. Construirá un árbol similar al DOM a partir del HTML, que luego podrá buscar los enlaces que desee y extraer cualquier contenido cercano que desee.

4

O considere mejorar HTML :: LinkExtor para hacer lo que quiera y enviar los cambios al autor.

+0

HTML :: LinkExtractor ya hace lo que sugeriste. –

5

Otra forma de hacerlo es usar XPath para consultar HTML analizado. Es necesario en casos complejos, como extraer todos los enlaces en div con clase específica. Utilice HTML :: TreeBuilder :: XPath para esto.

my $tree=HTML::TreeBuilder::XPath->new_from_content($c); 
    my $nodes=$tree->findnodes(q{//map[@name='map1']/area}); 
    while (my $node=$nodes->shift) { 
    my $t=$node->attr('title'); 
    } 
+2

Además, agregue $ tree-> delete para evitar pérdidas de memoria. –

4

respuestas anteriores eran perfectamente bien y sé que estoy tarde a la fiesta, pero esto empujaron en el [Perl] alimentan de manera ...

XML::LibXML es excelente para el análisis de HTML e inmejorable para la velocidad. Establezca la opción recover al analizar HTML mal formado.

use XML::LibXML; 

my $doc = XML::LibXML->load_html(IO => \*DATA); 
for my $anchor ($doc->findnodes("//a[\@href]")) 
{ 
    printf "%15s -> %s\n", 
     $anchor->textContent, 
     $anchor->getAttribute("href"); 
} 

__DATA__ 
<html><head><title/></head><body> 
<a href="http://www.google.com">Google</a> 
<a href="http://www.apple.com">Apple</a> 
</body></html> 

-yields-

 Google -> http://www.google.com 
     Apple -> http://www.apple.com 
6

Si eres aventurero y quiere probar sin módulos, algo como esto debería funcionar (adaptarlo a sus necesidades):

#!/usr/bin/perl 

if($#ARGV < 0) { 
    print "$0: Need URL argument.\n"; 
    exit 1; 
} 

my @content = split(/\n/,`wget -qO- $ARGV[0]`); 
my @links = grep(/<a.*href=.*>/,@content); 

foreach my $c (@links){ 
    $c =~ /<a.*href="([\s\S]+?)".*>/; 
    $link = $1; 
    $c =~ /<a.*href.*>([\s\S]+?)<\/a>/; 
    $title = $1; 
    print "$title, $link\n"; 
} 

Hay Probablemente algunas cosas hice mal aquí, pero funciona en un puñado de casos de prueba que intenté después de escribirlo (no cuenta para cosas como <img> etiquetas, etc.).

+0

eres el maestro, me ahorraste mucho tiempo ... gracias un montón. – run

-1

Podemos usar expresiones regulares para extraer el enlace con su texto de enlace. Esta es también la única forma.

local $/ = ''; 
my $a = <DATA>; 

while($a =~ m/<a[^>]*?href=\"([^>]*?)\"[^>]*?>\s*([\w\W]*?)\s*<\/a>/igs) 
{ 
    print "Link:$1 \t Text: $2\n"; 
} 


__DATA__ 

<a href="http://www.google.com">Google</a> 

<a href="http://www.apple.com">Apple</a> 
3

HTML::LinkExtractor es mejor que el HTML :: LinkExtor

Se puede dar tanto texto del enlace y el URL.

Uso:

use HTML::LinkExtractor; 
my $input = q{If <a href="http://apple.com/"> Apple </a>}; #HTML string 
my $LX = new HTML::LinkExtractor(undef,undef,1); 
$LX->parse(\$input); 
for my $Link(@{ $LX->links }) { 
     if($$Link{_TEXT}=~ m/Apple/) { 
      print "\n LinkText $$Link{_TEXT} URL $$Link{href}\n"; 
     } 
    } 
Cuestiones relacionadas