Webscrapping, extrayendo datos de la red.

webscrapping

 

Como programador, en algún momento habrás necesitado acceder alguna fuente de datos pública sin poder utilizar sus propias APIs.

Con PHP podemos extraer información de una web, aunque tambien se puede hacer de otras maneras que, aún siendo más eficaces, son bastante más complicadas de programar y requiere de altos conocimientos.

Yo, como dice el título de mi blog, prefiero hacerlo programando a mi manera.

Empecemos, ¿Qué es el WEB SCRAPPING?

El web scraping es una técnica que permite leer el contenido de un sitio web mediante un código o programa con la finalidad de extraer datos.
Entre los usos más comunes encontramos recolección de datos, comparación de precios, simulación de navegación, testing, etc.
 
El uso del web scraping es controvertido, debido a que muchas veces puede violar los términos y condiciones . Asegurate antes que el contenido que buscas sea público.
 
En esta entrada, voy a ofreceros un código con el que podreis extraer datos de empresas desde la página web de Páginas Amarillas. Es una herramienta que yo he utilizado bastante para proyectos personales y ahora lo pongo a vuestra disposición. Espero que os sirva.
 
Empecemos.

Funcionamiento del Scraper de Páginas Amarillas (PA)

El funcionamiento es simple aunque el desarrollo el algo confuso. Al final de esta entrada te pondré el código entero y podrás verlo en funcionamiento.

Vamos a empezar haciendo nuestra primera consulta, por ejemplo «dentistas en Castellón».

En este caso, nos ofrece 91 resultados.

Capturamos esta información desde nuestro formulario, al que hemos de añadir el LINK  de la consulta que hemos realizado en PA, que sería el siguiente:

https://www.paginasamarillas.es/search/dentistas/all-ma/castellon/all-is/castellon/all-ba/all-pu/all-nc/1?what=dentistas&where=castellon&ub=false&qc=true

Recibimos esta información y con éste sencillo código…

$consulta = file_get_contents($link_pag_am);
$resultados_totales= preg_replace('/[^0-9]+/', '', (strip_tags(extraeRegexp($consulta, '<div class="negocio">', '</span>')[0])));
$paginas= ceil($resultados_totales/30);

…contamos el total de resultados (ya hemos dicho que en este caso son 91), lo dividimos entre 30, que son los  resultados a mostrar por página y lo redondeamos hacia arriba por si hay menos de 30 resultados.

Extraer datos.

Ésta es la función más importante del programa, ya que se encarga de buscar en los resultados la información que queremos extraer. El funcionamiento es muy simple, le damos la cadena ($cadena) que hemos extradido y le decimos DESDE DONDE ($inicio) y HASTA DONDE ($fin)  queremos que nos busque la información.

function extraeRegexp($cadena, $inicio, $fin) {
preg_match_all('#' . $inicio . '(.*?)' . $fin . '#', $cadena, $matches);
return $matches[1];
}

Ésta función la utilizaremos cada vez que queramos un dato.

Mostrar tabla de resultados

Ahora que ya sabemos cuántas páginas de resultados tenemos, procederemos a extraer toda la información que necesitamos. Para esto, utilizaremos la segunda funcion que hemos llamado mostrarTabla();

En el inicio tenemos este código…

for ($i = 1; $i <= $paginas; $i++) {
$url = $link_pag_am;
$web = file_get_contents($url);
$urls = extraeRegexp($web, "<div class=\"envio-consulta\"><a href=\"", "\"");		
$total = array_merge($total, $urls);					
}

…que nos devuelve un array con todas las empresas que se muestran en cada una de las páginas.

Ahora ya podemos empezar a recorrer dicho array con un simple foreach;

foreach ($total as $url) {
            $web = file_get_contents($url);
            $nombre = extraeRegexp($web, '<h1 itemprop="name">', '</h1>')[0];
            $categoria = extraeRegexp($web, '<span class="category">', '</span>')[0];
            $telefono = extraeRegexp($web, '<span itemprop="telephone">', '</span>')[0];
            $direccion = extraeRegexp($web, '<span itemprop="streetAddress">', '</span>')[0];
            $cp = extraeRegexp($web, '<span itemprop="postalCode">', '</span>')[0];
            $ciudad = extraeRegexp($web, '<span itemprop="addressLocality">', '</span>')[0];
            $provincia = @extraeRegexp($web, '<span class="addressState">', '</span>')[0];
            $webaddress = @str_replace("?utm_campaign=paginasamarillas&utm_source=paginasamarillas&utm_medium=referral", "", extraeRegexp($web, 'class="fa icon-link"></i><a href="', '"')[0]);
        }

Y una vez llegues aquí, sólo te queda utilizar tus conocimientos para mostrar la información como necesites. Puedes generar una simple tabla, guardarlos en una base de datos o generar un archivo para conservarlos o enviarlos.

Seguramente, en función de la página de donde extraigas la información, necesitarás modificar el código para adaptarlo a la web que estás «scrapeando».

Espero que esta pequeña aportación te sea de utilidad. Aquí te dejo el código completo que yo he adaptado para mí  y un link para que puedas probarlo.

DEMOSTRACIÓN FUNCIONAMIENTO

<html>
    <head>
	<meta name="viewport" content="width=device-width, initial-scale=1"> 
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css">
        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js"></script> 
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    </head>
    <body>
        <div>
            <form class="form-control" style="background: black;padding: 2%">
                <input type="hidden" name="action" value="insert">
                <h5 style="color:white">Inserta la URL de la consulta en Paginas Amarillas:</h5>
                <input type="text" name="linkPA" class="form-control">
                <input style="margin-top: 5px" type="submit" class="btn btn-xs btn-info" value="CONSULTAR">     
            </form>
			
			<div id="loading" style="z-index: 999999999">
 <img style="margin-left:40%;width:20%" src="loader.gif"/><h6 style="text-align:center;font-weight:bold">CARGANDO RESULTADOS</h6>
</div>
			
			</div>
            <?php
            error_reporting(0);
            $action = filter_input(INPUT_GET, 'action');
            $link_pag_am = filter_input(INPUT_GET, 'linkPA', FILTER_SANITIZE_STRING);
			
$consulta = file_get_contents($link_pag_am);
$resultados_totales= preg_replace('/[^0-9]+/', '', (strip_tags(extraeRegexp($consulta, '<div class="negocio">', '</span>')[0])));
$paginas= ceil($resultados_totales/30);
 
            if ($action == 'insert' && !empty($link_pag_am)) {
                mostrarTabla($link_pag_am,$paginas);
            }

            function extraeRegexp($cadena, $inicio, $fin) {
                preg_match_all('#' . $inicio . '(.*?)' . $fin . '#', $cadena, $matches);
                return $matches[1];
            }

            function  mostrarTabla($link_pag_am,$paginas) {

                $total = [];
               for ($i = 1; $i <= $paginas; $i++) {
                    $url = $link_pag_am;
                    $web = file_get_contents($url);
                    $urls = extraeRegexp($web, "<div class=\"envio-consulta\"><a href=\"", "\"");		
                    $total = array_merge($total, $urls);					
					}
	
                ?>
                <div>
                    <table class="table table-sm table-striped table-bordered" style="width:100%">
                        <tr style="background:#847f7f; color:black; font-weight:bold">
                            <td>#</td><td>NOMBRE</td><td>PROVINCIA</td><td>CIUDAD</td><td>WEB</td>
                        </tr>


                        <?php
                        $number = 0;
                        foreach ($total as $url) {                            
                            $web = file_get_contents($url);
                            $webaddress = @str_replace("?utm_campaign=paginasamarillas&utm_source=paginasamarillas&utm_medium=referral", "", extraeRegexp($web, 'class="fa icon-link"></i><a href="', '"')[0]);
                            $urlparts = parse_url($webaddress);
                            $scheme = $urlparts['scheme'];
                            
                            if ($scheme === 'https' || $scheme === 'http') {
                                $number++;  //CONTADOR DE RESULTADOS-----------------
                                $nombre2 = extraeRegexp($web, '<h1 itemprop="name">', '</h1>')[0];
								$nombre=  preg_replace("%(<span.*?>)(.*?)(<\/span.*?>)%is","",$nombre2);
                                $ciudad = extraeRegexp($web, '<span itemprop="addressLocality">', '</span>')[0];
                                $provincia = @extraeRegexp($web, '<span class="addressState">', '</span>')[0];
                                if (is_null($provincia)) {
                                   $provincia = $ciudad;
                                }
                                ?>
                                <tr>
                                    <td><?= $number ?></td><td><?= $nombre ?></td><td><?= $provincia ?></td><td><?= $ciudad ?></td><td><a target="_blank" href="<?= $webaddress ?>"><?= $webaddress ?></a></td>
                                </tr>
                                <?php
                            }
                            /* $categoria = extraeRegexp($web, '<span class="category">', '</span>')[0];
                              $telefono = extraeRegexp($web, '<span itemprop="telephone">', '</span>')[0];
                              $direccion = extraeRegexp($web, '<span itemprop="streetAddress">', '</span>')[0];
                              $cp = extraeRegexp($web, '<span itemprop="postalCode">', '</span>')[0]; */
                        }
                        ?>
                    </table>
                </div>
    <?php
}
?>  
     <script>
$(document).ready(function(){
  $('#loading').hide();
  $('form').submit(function(){
    $('#loading').show();
  });
});
</script>  
    </body>
	
</html>

 

Compartir esta entrada.

One thought on “Webscrapping, extrayendo datos de la red.

  1. Hola, muy buen artículo, el problema es que me queda un poco lejos en cuanto a conocimientos. Hay alguna manera de acceder a algo programado para scrapear las paginas amarillas y obtener los emails de las empresas .

    Si me das un correo electrónico te escribo por privado.

    Muchas gracias

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

CAPTCHA ImageChange Image