Volver al blog
Guías
Sorin-Gabriel MaricaLast updated on Mar 31, 202612 min read

Extracción de datos web con PHP: la guía definitiva sobre la extracción de datos web

Extracción de datos web con PHP: la guía definitiva sobre la extracción de datos web

Internet es un espacio inmenso con más de 4.700 millones de usuarios, y no deja de crecer. Para ponerlo en perspectiva, más del 50 % de la población mundial utiliza Internet desde 2018.

Por supuesto, más usuarios también significan más datos. En este momento, Internet es tan grande que se estima que solo Google, Amazon, Microsoft y Facebook almacenan alrededor de 1,2 millones de terabytes.

Incluso una pequeña parte de esa información puede generar nuevas oportunidades de negocio. Teniendo esto en cuenta, no es de extrañar lo popular que se ha vuelto el web scraping.

Entender el web scraping

La gran cantidad de datos de Internet está lamentablemente dispersa por miles de millones de sitios web. Por ello, los desarrolladores necesitan una forma de recopilarlos y procesarlos para ofrecer a los usuarios nuevos productos innovadores. Sin embargo, la recopilación manual de información no es, en absoluto, una buena idea, ya que el volumen suele ser demasiado grande y los datos cambian continuamente.

La solución es extraerla automáticamente. Eso es, en pocas palabras, lo que hace el web scraping.

Por qué deberías extraer datos

Cuanta más información, más ideas, oportunidades y beneficios. Una vez procesada, puede resultar de un valor incalculable para ti o para tus clientes. Estas son solo algunas de las formas en que se puede utilizar el web scraping:

  • Herramientas de comparación de precios: extraer datos de múltiples sitios web para obtener una visión general de los precios de un tipo de producto.
  • Estudio de mercado: averiguar quiénes son tus competidores más importantes y qué están haciendo.
  • Aprendizaje automático: recopilar conjuntos de datos de entrenamiento y prueba para un modelo de aprendizaje automático.
  • Cualquier idea que requiera acceso a una cantidad considerable de datos.

Por ejemplo, un posible caso de uso es crear una aplicación nutricional que permita a los usuarios añadir sus comidas. Lo ideal sería que los usuarios simplemente abrieran la aplicación, buscaran los productos que han consumido, los añadieran a la herramienta y llevaran un control de cuántas calorías más pueden consumir después.

Sin embargo, la herramienta debe proporcionar una lista exhaustiva de todos los productos posibles y sus valores nutricionales. Esta lista se puede crear y actualizar automáticamente extrayendo la información nutricional de múltiples sitios web.

Los retos del web scraping

Aunque el web scraping resulta muy útil para quien utiliza el bot, a veces los sitios web no están dispuestos a compartir su contenido y pueden intentar impedirlo. Algunas de las formas en que pueden hacerlo son:

  • Códigos Captcha: cualquier página puede utilizar Captchas, aunque no se vean. Cuando realizas múltiples solicitudes, puede aparecer un código Captcha y bloquear tu rastreador web.
  • Bloqueo de IP: algunos sitios web optan por bloquear tu IP cuando detectan un tráfico excesivo procedente de tu lado.
  • Bloqueo geográfico: algunos contenidos pueden estar disponibles solo en países específicos, o es posible que recibas datos propios de una región cuando buscas información sobre otra.
  • JavaScript: la mayoría de los sitios web actuales utilizan JavaScript de una forma u otra. Algunos pueden mostrar su contenido de forma dinámica, lo que complica las cosas, ya que el código fuente de la página no es el mismo que el contenido de la página renderizada.

Superar estos retos puede requerir mucho trabajo, pero hay opciones. Para ayudarte, hemos creado WebscrapingAPI, que se encarga de todos estos problemas y te ayuda a crear tu solución más rápido y con menos dolores de cabeza.

Comprender la web

Cada vez que un usuario de Internet accede a un sitio web, el navegador crea una solicitud HTTP (Protocolo de Transferencia de Hipertexto). Puedes pensar en una solicitud como un mensaje del cliente (el ordenador del usuario) al servidor (el ordenador donde se encuentra el sitio web) en el que el cliente especifica lo que quiere recibir.

Por cada solicitud enviada, recibirás una respuesta. La respuesta puede ser satisfactoria o un error, como el famoso «código de error 404: página no encontrada». El contenido de un sitio web suele encontrarse en el cuerpo de la respuesta recibida del servidor.

Tanto las solicitudes como las respuestas contienen un encabezado y un cuerpo que se utilizan para intercambiar información. Además, las solicitudes pueden realizarse mediante varios métodos, siendo el más común el GET (que se utiliza al acceder a una página web). Estos métodos indican la acción que el cliente desea realizar.

Por ejemplo, al registrarse o actualizar su contraseña en un sitio web, usted desea que sus datos permanezcan ocultos en el navegador, y los sitios web pueden utilizar el método POST o PUT para este tipo de solicitud.

El encabezado de una solicitud contiene varias propiedades. Repasemos las más importantes:

  • Host: el nombre de dominio del servidor.
  • User-Agent: detalles sobre el cliente que realizó la solicitud, como el navegador y el sistema operativo.
  • Cookie: un conjunto de propiedades asociadas al cliente.
  • Accept: un parámetro utilizado para recibir la respuesta del servidor en un tipo específico, como text/plain o application/json.

Sin embargo, las solicitudes no son exclusivas de las páginas web. También se realizan para imágenes, estilos y código JavaScript, independientemente de la página. Puedes echar un vistazo a todas las solicitudes que realiza tu navegador Google Chrome al acceder a una página web pulsando F12 en una página, seleccionando la pestaña «Red» y actualizando la página en la que te encuentras. Al final deberías ver algo como esto:

Entender PHP

PHP es uno de los lenguajes de programación web más antiguos y populares utilizados para los backends de aplicaciones. Existe desde 1995 y ahora va por su octava versión.

Los programadores eligen este lenguaje de programación por su sintaxis sencilla y su facilidad de ejecución, ya que todo lo que se necesita para ejecutar código PHP es un equipo con PHP instalado. Además, dado que lleva tanto tiempo en el mercado, existen muchos recursos y asistencia para resolver y depurar errores de PHP.

PHP también cuenta con muchos frameworks y CMS (sistemas de gestión de contenidos) populares desarrollados en este lenguaje de programación. Algunos ejemplos famosos son WordPress, Drupal, Magento y Laravel.

No obstante, también presenta algunas desventajas. Por ejemplo, es más difícil extraer contenido dinámico en comparación con Python o JavaScript. Sin embargo, si solo necesitas información de páginas sencillas, PHP es sin duda una buena solución, y puede ayudarte a guardar o almacenar los datos extraídos con mucha más facilidad.

Lo que necesitarás

¿Todo bien hasta ahora? ¿Listo para crear tu primer rastreador web? Antes de empezar, debes tener una forma de ejecutar tu código PHP. Puedes elegir un servidor Apache/Nginx con PHP instalado y ejecutar el código directamente desde tu navegador, o puedes ejecutar el código desde la línea de comandos.

Hagámoslo más fácil utilizando una biblioteca para procesar el contenido extraído. Algunas de las bibliotecas de scraping de PHP más populares son Goutte, Simple HTML DOM, Panther y htmlSQL. Como alternativa, puedes optar por procesar el contenido utilizando expresiones regulares.

Para esta guía, utilizaremos Simple HTML DOM. Sin embargo, para solicitudes más avanzadas, también utilizaremos la biblioteca PHP llamada CURL.

Uso de Simple HTML DOM

Simple HTML DOM es una biblioteca desarrollada para versiones de PHP a partir de la 5.6, y nos permite acceder al contenido de la página de una forma mucho más sencilla: mediante selectores. Puedes descargar la biblioteca desde aquí, y también deberías leer la documentación.

Del archivo zip del enlace de descarga, solo necesitarás el archivo simple_html_dom.php, que debes colocar en la misma carpeta donde escribirás el código del scraper.

Para incluir la biblioteca en el código, solo necesitas esta línea de código:

include 'simple_html_dom.php'; // If the library is in another folder you should do include 'path_to_library/simple_html_dom.php'

Instalación de PHP-CURL

Aunque no siempre es necesario, tendrás que enviar diferentes encabezados para solicitudes más avanzadas. Usar la biblioteca PHP-CURL te ayudará.

Para instalarla en una máquina Ubuntu, puedes utilizar el siguiente comando:

sudo apt-get install php-curl

Tras instalar la biblioteca, no olvides reiniciar tu servidor Apache/Nginx.

Crear tu propio rastreador web

Ahora que tenemos todo lo necesario, ¡es hora de extraer datos! En primer lugar, debes decidir qué sitio web y qué contenido quieres rastrear. Para este artículo, rastrearemos el contenido de la lista de películas mejor valoradas de IMDB.

1. Inspecciona el contenido del sitio web

La mayor parte del contenido web se muestra utilizando HTML. Dado que necesitamos extraer contenido específico del código fuente HTML, también es necesario comprenderlo. Primero debemos inspeccionar cómo se ve el código fuente de la página para saber qué elementos extraer de ella.

Puedes hacerlo en Google Chrome haciendo clic con el botón derecho del ratón sobre el elemento que deseas extraer y seleccionando «Inspeccionar elemento». Esto debería abrir una ventana en tu navegador con el código fuente de la página y los estilos aplicados a los elementos. En esta ventana, la única pestaña que necesitamos consultar es «Elementos», que nos mostrará cómo está estructurado el DOM HTML de la página.

Por ejemplo, la página contiene una tabla con las clases «chart» y «full-width» en la imagen de arriba. En esta tabla, cada celda tiene su propia clase (posterColumn, titleColumn, etc.), que podemos utilizar para crear un selector. Así, podremos acceder únicamente a los datos necesarios.

¿Confuso? No te preocupes, los siguientes pasos te lo aclararán todo.

2. Enviar una solicitud desde PHP

Enviar una solicitud, en este caso, significa básicamente acceder al HTML de una página directamente con código PHP. Hay dos formas de hacerlo.

En primer lugar, podemos utilizar la biblioteca PHP-CURL, que también nos permite modificar los encabezados y el cuerpo que enviamos en nuestra solicitud.

<?php
 
header("Content-Type: text/plain"); // We choose to display the content as plain text
 
$ch = curl_init("https://www.imdb.com/chart/top/");
curl_setopt($ch, CURLOPT_HEADER, 0);
$response = curl_exec($ch); // Running the request
 
if (curl_error($ch)) {
    echo curl_error($ch); // Displaying possible errors from the request
} else {
    echo $response; // Displaying the content of the response
}
 
curl_close($ch);
?>

Otra opción es una línea de código, utilizando el método file_get_contents($url), pero esto puede resultar insuficiente en algunos casos. Para enviar encabezados a esta solicitud, debes utilizar un contexto creado con el método stream_context_create.

<?php

header("Content-Type: text/plain"); // We choose to display the content as plain text

echo file_get_contents('https://www.imdb.com/chart/top/'); // We retrieve and display the contents of the response in a single line

?>

Debes decidir qué método utilizar en función de la complejidad del rastreador que quieras crear.

Los dos fragmentos de código anteriores mostrarán el código fuente HTML de la página que estamos rastreando, el mismo que se ve al inspeccionar el sitio web. Usaremos la primera línea del código para mostrar los resultados como texto sin formato (text/plain). De lo contrario, se renderizará directamente como HTML.

Si hay alguna diferencia en la estructura HTML, significa que hay un código JavaScript ejecutándose en el sitio web y cambiando el contenido una vez que el usuario accede a él. Hemos preparado un consejo sobre cómo lidiar con eso más adelante en el artículo.

3. Extraer los datos

De la página elegida, extraeremos solo el título de las películas y la valoración asociada a cada una de ellas. Como vimos anteriormente, el contenido se muestra en una tabla en la que cada celda tiene su clase.

Utilizando esto, podemos optar por extraer todas las filas de la tabla. A continuación, revisamos cada fila individual en busca de las celdas que nos interesan.

El siguiente fragmento de código debería hacer precisamente eso:

<?php
 
header("Content-Type: text/plain"); // We choose to display the content as plain text
 
include 'simple_html_dom.php';
 
$html_dom = file_get_html('https://www.imdb.com/chart/top/'); // We retrieve the contents using file_get_html from simple_html_dom
$table_rows = $html_dom->find('table.chart tbody tr'); // Getting all of the table rows
foreach($table_rows as $table_row) {
    $title_element = $table_row->find('.titleColumn a', 0);
    $rating_element = $table_row->find('.ratingColumn strong', 0);
    if (!is_null($title_element) && !is_null($rating_element)) { // Checking if the row has a title and a rating column
        echo $title_element->innertext . ' has rating ' . $rating_element->innertext . PHP_EOL; // If it does then we print it
    }
}
 
?>

Como puedes observar, hemos utilizado el selector «table.chart tbody tr» para extraer todas las filas de la tabla. Es recomendable utilizar selectores lo más específicos posible para poder diferenciar los elementos que necesitas del resto.

Tras recuperar las filas, las recorrimos en un bucle, buscando elementos con la clase titleColumn o ratingColumn. Si el código encontraba alguno, mostraba su propiedad innerText.

Es importante señalar que en este ejemplo hemos utilizado file_get_html en lugar de file_get_contents. Esto se debe a que esta función procede de la biblioteca simple_html_dom y actúa como envoltura de la función file_get_contents.

4. Exportar los datos

En los ejemplos anteriores, recopilamos los datos del sitio y los mostramos directamente en la pantalla. Sin embargo, también puedes guardar los datos en PHP con bastante facilidad.

Puedes guardar los datos extraídos en un archivo .txt, como JSON, como CSV, o incluso enviarlos directamente a una base de datos. PHP es muy bueno para eso. Solo tenemos que almacenarlos en una matriz y poner el contenido de la matriz en un nuevo archivo.

<?php
 
include 'simple_html_dom.php';
 
$scraped_data = [];
 
$html_dom = file_get_html('https://www.imdb.com/chart/top/'); // We retrieve the contents using file_get_html from simple_html_dom
$table_rows = $html_dom->find('table.chart tbody tr'); // Getting all of the table rows
foreach($table_rows as $table_row) {
    $title_element = $table_row->find('.titleColumn a', 0);
    $rating_element = $table_row->find('.ratingColumn strong', 0);
    if (!is_null($title_element) && !is_null($rating_element)) { // Checking if the row has a title and a rating column
        $scraped_data[] = [
            'title' => $title_element->innertext,
            'rating' => $rating_element->innertext,
        ];
    }
}
 
file_put_contents('file.json', json_encode($scraped_data)); // Saving the scraped data in a .json file
 
// Saving the scraped data as a csv
$csv_file = fopen('file.csv', 'w');
fputcsv($csv_file, array_keys($scraped_data[0]));
 
foreach ($scraped_data as $row) {
    fputcsv($csv_file, array_values($row));
}
 
fclose($csv_file);
 
?>

El código anterior toma el mismo contenido que extrajimos anteriormente y crea dos archivos, uno CSV y otro JSON, con todas las películas mejor valoradas y sus puntuaciones.

Consejos y trucos

1. Gestión de errores

Al programar en PHP y extraer datos de sitios web que pueden cambiar en cualquier momento, es normal que aparezcan errores. Un buen fragmento de código que puedes utilizar para la depuración son las siguientes tres líneas, colocadas al principio de cualquier script PHP:

ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);

Esto te ayudará a identificar problemas en tu código más rápidamente y a actualizar tu script cuando sea necesario.

2. Configuración de encabezados en solicitudes para PHP

A veces, al realizar una solicitud, es posible que también tengas que enviar algunos encabezados. Por ejemplo, al trabajar con una API, puede que sea necesario un token de autorización, o quizá quieras que el contenido se reciba en formato JSON en lugar de texto sin formato. Puedes añadir encabezados tanto con curl como con file_get_contents. A continuación te mostramos cómo hacerlo con curl:

$ch = curl_init("http://httpbin.org/ip");
curl_setopt($ch, CURLOPT_HEADER, [
    'accept: application/json'
]);
$response = curl_exec($ch); // Running the request

Y para file_get_contents:

$opts = [
    "http" => [
        "method" => "GET",
        "header" => "accept: application/json\r\n"
    ]
];
$context = stream_context_create($opts);
$result = file_get_contents("http://httpbin.org/ip", false, $context);

3. Uso de curl o file_get_contents con simple_html_dom

Cuando extrajimos contenido de IMDB, utilizamos la función file_get_html de simple_html_dom para realizar el scraping. Este enfoque funciona para solicitudes sencillas, pero no necesariamente para las más complicadas. Si necesitas enviar encabezados, es mejor que utilices uno de los métodos descritos en el consejo anterior.

Para utilizarlos en lugar de file_get_html, basta con extraer el contenido y luego usar str_get_html para convertirlo en un objeto DOM, así:

$opts = [
    "http" => [
        "method" => "GET",
        "header" => "accept: text/html\r\n"
    ]
];
$context = stream_context_create($opts);
$result = file_get_contents("https://www.imdb.com/chart/top/", false, $context);
$html_dom = str_get_html($result);

Además, ten en cuenta que simple_html_dom tiene por defecto algunos límites (que se pueden consultar en el archivo simple_html_dom.php). Por ejemplo, el contenido del sitio web puede tener hasta 600 000 caracteres. Si quieres cambiar este límite, solo tienes que definirlo al principio de tu código antes de incluir la biblioteca simple_html_dom:

define('MAX_FILE_SIZE', 999999999);

4. Extracción de contenido dinámico

Si estás extrayendo datos de un sitio web dinámico, tendrás que acceder a él como lo haría un navegador. De lo contrario, no podrás extraer los datos reales y obtendrás código JavaScript en su lugar.

Tendrás que instalar un controlador de navegador, como chromium-chromedriver o firefox-geckodriver. Extraer el contenido dinámico en PHP es una lección más avanzada, pero si te interesa, puedes intentar hacerlo leyendo la documentación de la biblioteca panther.

Como alternativa, una solución mucho más sencilla es utilizar WebScrapingAPI, que resuelve la mayoría de los problemas. La API supera los bloqueos de IP y los Captchas utilizando nuestra red de proxies, al tiempo que ejecuta JavaScript. El resultado: dispones de un scraper avanzado de inmediato, lo que reduce el tiempo de desarrollo y de espera.

Aquí tienes un ejemplo de código que mostrará el contenido de https://httpbin.org/ip directamente en PHP, a través de nuestra API:

$content = 
file_get_contents("https://api.webscrapingapi.com/v1?pi_key=YOUR_API_KEY&url=". urlencode('https://httpbin.org/ip'));
echo $content;

Conclusión

¡Enhorabuena por llegar hasta el final! Ahora deberías tener todo lo necesario para crear tu rastreador web con PHP. Aunque en este artículo solo hemos explorado la biblioteca simple_html_dom, puedes probar otras bibliotecas populares y ver por ti mismo cuál te conviene más.

Recuerda que los sitios web cambian constantemente y que sus datos pueden actualizarse de la noche a la mañana. Para ayudarte con esto, puedes utilizar selectores más específicos. Por supuesto, no hay garantía de que tu scraper funcione para siempre, pero es un comienzo. Por eso los web scrapers requieren actualizaciones continuas que consumen mucho tiempo.

Si no te apetece dedicar todo ese tiempo a investigar y adaptar tu código, ¡siempre puedes probar la versión de prueba gratuita de WebScrapingAPI!

Acerca del autor
Sorin-Gabriel Marica, Desarrollador full-stack @ WebScrapingAPI
Sorin-Gabriel MaricaDesarrollador full-stack

Sorin Marica es ingeniero Full Stack y DevOps en WebScrapingAPI, donde se encarga de desarrollar funciones para los productos y de mantener la infraestructura que garantiza el buen funcionamiento de la plataforma.

Empieza a crear

¿Estás listo para ampliar tu recopilación de datos?

Únete a más de 2000 empresas que utilizan WebScrapingAPI para extraer datos de la web a escala empresarial sin ningún gasto de infraestructura.