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:

Índice
  1. Descargando el código html en local o en red
  2. Buscar tags html por su nombre
  3. Extraer valores de los atributos de las etiquetas html
  4. Filtrando etiquetas html en base a sus atributos
  5. Coincidencia de patrones al filtrar elementos por sus atributos
  6. Añadiendo y/o cambiando atributos de las etiquetas
  7. Buscar el enésimo elemento de una etiqueta
  8. Modificando el texto contenido delimitado por una etiqueta
  9. Añadir una etiqueta contenedora
  10. 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);
¡Haz clic para puntuar esta entrada!
(Votos: 4 Promedio: 5)
  1. Rony dice:

    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!

    1. Nacho dice:

      Hola Rony,

      si te fijas en el post un poco mas arriba esta indicado la opción por la que preguntas "comienza por (^)". Utilizando el operador ^ se puede hacer lo que deseas.

  2. admin dice:

    Gracias Andrés, me alegro que te haya sido útil.

  3. Andrés dice:

    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

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

Subir