Scraping con PHP Simple HTML DOM, segunda parte
Como vimos en el articulo anterior "Hacer web scraping con PHP Simple HTML DOM Parser", si estamos interesados en extraer código html de una pagina web con php, la biblioteca PHP Simple HTML Dom es una de las mejores opciones.
A continuación, mostrare unos ejemplo en código sobre como utilizar esta biblioteca de php:
- Descargando el código html en local o en red
- Buscar tags html por su nombre
- Extraer valores de los atributos de las etiquetas html
- Filtrando etiquetas html en base a sus atributos
- Coincidencia de patrones al filtrar elementos por sus atributos
- Añadiendo y/o cambiando atributos de las etiquetas
- Buscar el enésimo elemento de una etiqueta
- Modificando el texto contenido delimitado por una etiqueta
- Añadir una etiqueta contenedora
- Evitar problemas de memoria
Descargando el código html en local o en red
Podemos obtener de varias formas el código html que queremos procesar. PHP Simple HTML permite
- Obtener el código html de una pagina web
- Obtener el html de un fichero local
- Definir nosotros el código html a procesar
<?php include('simple_html_dom.php'); //Si queremos obtener el código html de una pagina web $html = file_get_html("https://google.es"); //Si queremos procesar un fichero en local indicando su ruta relativa $html = file_get_html("index.html"); //Si queremos procesar un fichero en local indicando su ruta absoluta $html = file_get_html("/home/nacho/index.html"); //Si queremos procesar la cadena de texto html indicada por nosotros $html = str_get_html("<html><head><title>Prueba</title></head><body><h2>Biblioteca PHP Simple HTML DOM</h2><p>A HTML DOM parser written in PHP5+ let you manipulate HTML in a very easy way!</p></body></html>"); //Obtener el codigo de una web y almacenarla en la variable $data $data = file_get_contents("https://google.es"); //Pasamos el contenido de la pagina a la biblioteca PHP Simple HTML $html = str_get_html($data); ?>
Buscar tags html por su nombre
Podemos localizar elementos html buscando por su nombre. Por ejemplo, si queremos extraer todos los enlaces, buscamos todos las etiquetas html "a":
<?php include('simple_html_dom.php'); $html = file_get_html('https://elmundo.es/'); //Obtenemos todos los enlaces de la web $enlaces = array(); foreach($html->find('a') as $a) { $enlaces[] = $a->href; } print_r($enlaces); //Obtener todas las imagenes de la web $imagenes = array(); foreach($html->find('img') as $img) { $imagenes[] = $img->src; } print_r($imagenes); //obtener el h1 de la web $titulares = array(); foreach($html->find('h1') as $h1) { $titulares[] = $h1->plaintext; } print_r($titulares); ?>
Extraer valores de los atributos de las etiquetas html
Imagina que quieres obtener el texto alternativo de cada imagen de una pagina web. Es sencillo, tan solo debemos obtener todas las imágenes de la web y luego comprobar si existe el atributo alt de la misma.
<?php include('simple_html_dom.php'); $html = file_get_html('https://elmundo.es/'); foreach($html->find('img') as $link) { if ($link->alt) { echo $link->alt.'<br />'; } } ?>
Filtrando etiquetas html en base a sus atributos
En el siguiente ejemplo obtendremos los enlaces que estén dentro de un h5 cuya clase sea "list-group-item-heading":
<?php include('simple_html_dom.php'); $url = 'https://www.gsmspain.com/foros/f1_General.html'; $html = file_get_html($url); $links = array(); foreach($html->find('h5[class="list-group-item-heading"] a') as $a) { $links[] = $a->href; } print_r($links); ?>
Si queremos ahorrar escribiendo, podemos utilizar los atajos . y # para indicar las clases e ids del elemento html. Por ejemplo, estas dos expresiones son la misma:
foreach($html->find('h5[class="list-group-item-heading"] a') as $a) foreach($html->find('h5.list-group-item-heading a') as $a)
Coincidencia de patrones al filtrar elementos por sus atributos
Imaginemos que necesitas obtener los enlaces internos de una web. Podemos utilizar el operador "comienza por" (^). Por ejemplo obtener los enlaces cuya url de destino comienza por "https://www.gsmspain.com/foros/":
<?php include('simple_html_dom.php'); $url = 'https://www.gsmspain.com/foros/f1_General.html'; $html = file_get_html($url); $links = array(); foreach($html->find('a[href^="https://www.gsmspain.com/foros/"]') as $a) { $links[] = $a->href; } print_r($links); ?>
Podemos usar el operador "contiene" (*), por ejemplo, para obtener los enlaces que contiene "gsmspain.com" en su atributo href:
foreach($html->find('a[href*="gsmspain.com"]') as $a)
Hay otro operador "finaliza con" ($), que nos permite seleccionar las etiquetas html donde alguno de su atributo "finaliza con". Por ejemplo tenemos dos elementos div con ids "x_elemento":
<div id="1_elemento">Elemento 1</div> <div id="2_elemento">Elemento 2</div>
Si queremos seleccionarlos, tan solo debemos escribir:
foreach($html->find('div[id$="_elemento"]' as $div)
Añadiendo y/o cambiando atributos de las etiquetas
PHP Simple HTML tambien nos permite modificar los atributos de las etiquetas html. Por ejemplo modificar/añadir o eliminar las clases o ids de las etiquetas:
<p class="oculto">Este texto tiene la clase oculto y no se ve</p>
Si queremos modificar la clase de la etiqueta p y sustituirla por la clase "visible", es sencillo:
foreach($html->find('p.oculto') as $p) { $p->class = 'visible'; }
Buscar el enésimo elemento de una etiqueta
En ocasiones necesitamos encontrar el elemento numero x de una etiqueta. Si deseamos obtener la url del tercer enlace de una web, tan solo deberíamos hacer:
echo $html->find('a',2)->href;
Hay que tener en cuenta que los elementos se comienzan a numerar en cero, por lo que el elemento 2 sera el tercer enlace.
Modificando el texto contenido delimitado por una etiqueta
También es posible modificar el texto contenido en una etiqueta. Por ejemplo tenemos la etiqueta "p":
<p id="contenido">Este texto esta contenido dentro de una etiqueta</p>
//Añadimos el texto de la etiqueta p "contenido" $html->find('p#contenido',0)->innertext .= ' parrafo'; //Borrar el texto de la etiqueta p "contenido" $html->find('p#contenido',0)->innertext = '';
Añadir una etiqueta contenedora
Si necesitamos añadir una capa contenedora, podemos hacerlo de manera sencilla. Utilizando el ejemplo anterior si tenemos:
<p id="contenido">Este texto esta contenido dentro de una etiqueta</p>
$html->find('p#contenido',0)->outertext = ' <div id="contenedor">' . $html->find('p#contenido',0)->outertext. '</div> ';
Evitar problemas de memoria
Una vez empecemos a usar esta biblioteca, empezaremos a manejar multitud de datos, lo que puede provocar fugas de memoria, dejando parte de la memoria sin liberar.
La mejor manera de evitar este problema es liberando correctamente la memoria:
$html->clear(); unset($html);
Una librería muy interesante que no conocía y que creo que utilizaré en más de un proyecto que tengo en mente. Gracias por el aporte!
Deja una respuesta
Hola, gracias por el aporte, excelentemente explicado, así como se puede buscar como finaliza (operador «finaliza con» ($)), ¿existe alguna manera de buscar por como comienza? Gracias!