Haciendo Screen Scrapping


 

El Screen Scrapping o “respaldo de pantalla”, es una técnica usada para extraer automáticamente información de un documento, un documento puede ser una página web, un archivo PDF, un archivo de Word, etc.

Ejemplos de Uso de Screen Scrapping:

–          El Screen Scrapping es usado mucho por motores de búsqueda (Web Scrapping) para obtener información de páginas y obtener el contenido HTML.

–          También es usado para obtener información en tiempo real, supongamos una página donde se nos muestra el precio de un producto, y necesitamos estar revisando el precio para ver si lo podemos comprar, en vez de estar nosotros actualizando la página y verificar el precio, podemos usar una aplicación que nos obtendrá el precio automáticamente y nos enviara una alarma cuando sobrepase un límite.

–          Es usado para obtener las URL de una página, o las imágenes que ella tiene.

Para muchas empresas esta técnica inflige los términos legales, por eso aquí lo vamos a usar meramente como estudio.

¿Qué vamos a hacer?

En nuestro ejemplo, vamos a usar la clase WebClient, con esta clase podemos obtener el html de una página web, después de obtenerlo vamos a extraer las URL que la página se encuentre usando, esta extracción se hará con expresiones regulares.

Creamos un proyecto nuevo de Windows Forms, modificamos el formulario adicionando:

–          Un Texto para escribir la página web que queremos obtener el HTML (name = txtURL)

–          Un botón para ejecutar el proceso

–          Un Texto donde vamos a mostrar el resultado de la página (name = txtResult, Multiline = true, ScrollBars = Both)

 aplicacion screen scrapping

El código del botón:

private void button1_Click(object sender, EventArgs e)
{
  if(String.IsNullOrEmpty(txtURL.Text))
  {
   MessageBox.Show("Por favor escriba una URL.");
   txtURL.Focus();
   return;
  }
  try
  {
   using (WebClient cliente = new WebClient())
   {
     txtResult.Text=  cliente.DownloadString(txtURL.Text);
   }
  }
  catch (Exception ex)
  {
    MessageBox.Show("Se presento un error: " + ex.Message);
  }
}

 Primero verificamos que se haya escrito algo en el texto, luego creamos un objeto WebClient, el using es usado para definir un ámbito de una variable, el using libera automáticamente la memoria utilizada por el objeto, cabe recordar que los objetos usados en la instrucción using, deben implementar la Interface IDisposable.

Con el método DownloadString obtenemos el html de la página:

aplicacion1

 Muchas veces, necesitaremos enviar un agente de usuario  para obtener el html de una página, como por ejemplo, que sucede si intentamos obtener el html de la siguiente dirección:

http://www.bolsar.com/NET/Cotizaciones/PreciosOnline/IntradiarioIndices.aspx?indice=MERVAL

 error500

Cuando se solicita una página web, el explorador envía una serie de encabezados al servidor web que hospeda el sitio que está visitando. Cada encabezado contiene detalles que ayudan al servidor web a determinar la mejor manera de ofrecer la información que se ha solicitado.”

Para evitar el error, modificamos nuestro código y adicionamos un user agent a la cabecera del WebClient:

using (WebClient cliente = new WebClient())

      {

        cliente.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");

        txtResult.Text=  cliente.DownloadString(txtURL.Text);

      }

 

Ahora si ejecutamos el código:

aplicacion2

Si algunos tienen conexión de Internet lenta podrán ver que al presionar el botón de obtener el html de la página, la aplicación se queda esperando la respuesta, para evitar que el proceso bloquee la aplicación, la clase WebClient tiene métodos asíncronos, así los procesos se ejecutaran en Background y la aplicación no se bloqueara.

Modificamos el código para llamar el método DownloadStringAsync, este método recibe como parámetro un variable de tipo Uri, por lo tanto debemos convertir nuestra cadena del Texto URL, en tipo Uri, y además el método no retorna nada, el código quedaría así:

using (WebClient cliente = new WebClient())

      {

       cliente.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");

       cliente.DownloadStringAsync(new Uri(txtUrl.Text));

      }

Para manejar los métodos asíncronos, debemos asignarle funciones a los eventos de la clase, cuando se termina de descargar el HTML, se ejecuta el método DownloadStringCompleted, para adicionarle una función, hacemos lo siguiente:

client.DownloadStringCompleted += y luego presionamos TAB dos veces, se creara automáticamente la función y el Delegado:

cliente.DownloadStringCompleted += new DownloadStringCompletedEventHandler(cliente_DownloadStringCompleted);

Se creó una función llamada cliente_DownloadStringCompleted.

En esta función adicionamos el código que queramos que se ejecute cuando se completo la descarga de la página:

void cliente_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)

     {

      if (e.Error == null)

         {

          txtResult.Text = e.Result;

         }

      else

         {

          txtResult.Text = e.Error.Message;

         }

     }

Si probamos vemos que todo funciona nuevamente, ahora para mostrar el proceso agregamos un control ProgressBar a nuestro formulario, y luego debemos adicionar un delegado al método DownloadProgressChanged para que la barra de progreso se actualice:

cliente.DownloadProgressChanged += new DownloadProgressChangedEventHandler(cliente_DownloadProgressChanged);

y en la función creada agregamos lo siguiente:

 

void cliente_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)

     {

      progressBar1.Value = e.ProgressPercentage;

     }

e.ProgressPercentage contiene el valor del progreso del proceso. Ahora si ejecutamos el código:

 aplicacionprogressbar

Bien, ahora seguimos con el Screen Scrapping, vamos a crear una función que nos entregue todas las direcciones web usadas en la página.

Adicionamos un listBox donde vamos a mostrar los resultados obtenidos.

Vamos a usar la clase Regex del namespace System.Text.RegularExpressions, esta clase recibe como parámetro una expresión regular, lo que vamos a obtener son todas las cadenas que estén de la forma: https o “http://direccionweb”, usamos la siguiente expresión regular:

https?:[^»»]*

Explicación:

–          http: Esto indica que lo que buscamos empieza con esa parte

–          s? : indica que el carácter s es opcional, o sea que pueden coincidir http o https

–          : indica que la palabra sigue con :

–          [^””]* : Esto es una negación, lo que quiere decir es que encuentre todo menos el símbolo “, en cuanto se encuentre una cadena que contenga al final “ se deja de buscar, el * significa que se puede repetir muchas veces.

En una próxima publicación veremos mucho mejor las expresiones regulares. Para más información esta página o en la wiki.

Nuestro código quedaría así:

void cliente_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e) 

     {

      if (e.Error == null)

        {

         txtResult.Text = e.Result;

         // Extraer las URL

         String patron = @"https?:[^""]*"

         Regex r = new Regex(patron);

         MatchCollection mcl = r.Matches(txtResult.Text);

 

         foreach (Match ml in mcl)

          {

           listBox1.Items.Add(ml.Value);

          }

        }

       else

        {

         txtResult.Text = e.Error.Message;

        }

     }

La clase MatchCollection contiene todas las cadenas que han coincidido con la expresión regular, recorremos la colección y adicionamos a la lista los valores encontrados.

Si ejecutamos el código:

 aplicacion3

Para más información sobre Screen Scraping aquí .

El código fuente de la aplicación AQUI.

6 pensamientos en “Haciendo Screen Scrapping

    • Hola, ese ml es el objeto de la colección mcl, en el mismo foreach se está declarando, creo que en visual basic sería algo como:
      For Each ml As Match In mcl
      listBox1.Items.Add(ml.Value);
      Next ml

  1. Hola amigo! Este post esta muy interesante, quiero hacer lo mismo pero quiero extraeer el valor de una etiqueta html a través de su id.
    Me prodias ayudar a tener una idea de como hacer esto? Le agradecería mucho.

Replica a guillermo Cancelar la respuesta