Extraer enlaces de una URL con Java

De ChuWiki

En este ejemplo vamos a cargar una URL de internet y usando una expresión regular extraeremos todos los enlaces en los href. Vamos allá con el código, que tienes disponible en ExtractLinksFromUrl.java


El código[editar]

El código java para extraer los enlaces de una página web puede parecerse a este

package com.chuidiang.ejemplos;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Extrae los links de una url de internet. Abre la URL, carga el contenido en
 * un String y por medio de una expresion regular busca los href="enlace"
 * 
 * @author Chuidiang
 * 
 */
public class ExtractLinksFromUrl {

   public static void main(String[] args) throws Exception {
      String content = extractContent("http://www.chuidiang.com");
      showLinks(content);
   }

   private static String extractContent(String urlString)
         throws MalformedURLException, IOException {
      URL url = new URL(urlString);
      URLConnection urlConnection = url.openConnection();
      InputStream is = urlConnection.getInputStream();
      BufferedReader br = new BufferedReader(new InputStreamReader(is));
      String content = "";
      String linea = br.readLine();
      while (null != linea) {
         content += linea;
         linea = br.readLine();
      }
      return content;
   }

   private static void showLinks(String content) {
      Pattern pattern = Pattern.compile("(?i)HREF\\s*=\\s*\"(.*?)\"");
      Matcher matcher = pattern.matcher(content);
      while (matcher.find()) {
         System.out.println(matcher.group(1));
      }
   }

}


Lectura de la URL[editar]

Para leer la URL, dentro del método extractContent(), creamos una URLConnection con la URL de nuestra página web, abrimos la conexión y pedimos el InputStream para empezar a leer. Para facilitar la lectura y no leer en bytes, usamos un BufferedReader que nos permite leer líneas.

Vamos leyendo línea a línea en un bucle y añadiendo el contenido a la variable content. Al final del bucle, content tendrá todo el código html de la página web.

Una cosa a tener en cuenta es que los readLine() no nos devuelven los retornos de carro que haya en el código html de la página, por lo que el String content en el que metemos todo el contenido será de una sola línea.


La expresión regular[editar]

En el método showLinks() usamos una expresión regular para obtener todos los enlaces en href="....". Explicamos la expresión regular

  • (?i) Hace que a partir de aquí se ignoren mayúsculas y minúsculas. Eso es importante para poder poner HREF en la expresión regular sin preocuparnos y no tener que poner algo como esto [Hh][Rf][Ee][Ff]
  • HREF Pues eso, href
  • \\s* Todos los espacios en blanco que hagan falta o ninguno. Esto permite que se reconozcan los enlaces aunque haya espacios entre href y el = que va detrás.
  • = El igual
  • \\s* Otra vez todos los espacios que hagan falta, de forma que se reconozca aunque haya espacios entre el = y las " de apertura
  • \" Las comillas de apertura
  • (.*?) Todos los caracteres que haya. El ? detrás de .* indica que se use en modo "reluctant". Si no lo ponemos, se cogerían todos los caracteres hasta las últimas " de la página web, y no sólo hasta el primer cierre de comillas (el siguiente apartado detalla esto de una forma más clara). Se mete .*? entre paréntesis porque este es el trozo en el que tenemos interés, así podemos recuperarlo después.
  • \" Las comillas de cierre

Bien, posiblemente podemos encontrar pegas y quizás necesitemos alguna expresión regular más elaborada, pero de momento nos vale.

Después de compilar la expresión regular, obtenemos el matcher y llamando sucesivamente a su método find() obtenemos los sucesivos enlaces. find() devuelve true si ha encontrado otro enlace y false en caso contrario, así que un while(matcher.find()) nos vale para el bucle (mientras encuentres algo ....).

Dentro del bucle, matcher.group(1) nos devuelve el contenido.


reluctant[editar]

Si en la expresión regular no ponemos el ? en la parte \"(.*?)\", nos pasaría lo siguiente. Imagina que el contenido HTML es este

<a href="enlace1">uno</a><a href="enlace2">dos</a>

Si no ponemos el interrogante, la expresión casaría todo desde las primeras comillas hasta la última, es decir, el resultado sería

enlace1">uno</a><a href="enlace2

Al poner el ?, la expresión regular es "reacia (reluctant)" a coger muchos caracteres y coge los menos posibles, es decir, lo justo entre unas comillas y las siguientes.


Enlaces[editar]