Programando un web crawler PHP, con Laravel en WordPress

¡Qué tal! En el post de ayer expliqué cómo instalar Laravel en WordPress y se planteó un pequeño debate. A bastantes personas les gustó, pero algunos comentáis que el artículo explica pocas cosas, y otros os preguntáis por qué os puede interesar meter un framework MVC dentro de un CMS.

Bueno, ya sabéis… En mi humilde opinión esto es lo que tiene el mundo de la programación, ¿verdad? La experiencia, las ganas y el conocimiento de los programadores suelen variar muchísimo. Tanto es así que un post de desarrollo de apps puede ser muy difícil para unos mientras que los más expertos lo pueden encontrar incluso aburrido.

No me extenderé mucho con posts de programación porque tengo seguidores que no son programadores y los pobres se van a aburrir con cuestiones tan técnicas como las que debatimos ahora. ¡No os vayáis! 😀

Programando un web crawler PHP, con Laravel en WordPress

Ok, os voy a contar un secreto…

¡Me he propuesto implementar algunas herramientas SEO en mi blog! También me gustaría meter micro-aplicaciones, APIs, etc. ¿Lo conseguiré? Como comenté, el objetivo que persigo es poder ejecutar apps así, con este lenguaje URL:

https://programarivm.com/apps/mi-super-herramienta-seo/

De modo que hablar de herramientas SEO significa hablar de web crawlers.

¿Qué es un web crawler?

Los web crawlers, también llamados scrapers, robots araña o bots son programas informáticos que rastrean las páginas webs en busca de enlaces, analizándolos uno a uno. Es lo que hacen los motores de búsqueda que conocemos: Google, Bing, Yahoo!, Yandex, etc.

Un scraper puede utilizar esta estrategia para recorrer los enlaces de una página web:

  • Primero se mete en la página de inicio (nivel 0)
  • Encuentra todos los enlaces de la página de inicio (nivel 1)
  • Se mete en todos y cada uno de los enlaces del nivel 1 y encuentra todos los enlaces del nivel 2
  • Y así sucesivamente

Parece muy fácil, ¿cierto?

Pero no lo es tanto. Desde un punto de vista teórico, un programa como el descrito arriba tiene que invertir mucho tiempo en rastrear los enlaces. En jerga informática se dice que tiene una complejidad temporal alta. Es un algoritmo costoso y el ordenador se cuelga de tanto pensar.

Lo ideal es utilizar algoritmos que implementen estrategias de rastreo óptimas.

En mi caso, como no tengo tiempo de estudiar a fondo este tema, ni conozco el estado del arte de esta tecnología, ni puedo investigar algoritmos de optimización, ni tampoco quiero aburrir a la gente que me sigue y que no programa aplicaciones…

En mi caso opto por la solución más sencilla de todas. Lo más fácil es sacar los enlaces de un mapa de sitio web, de un sitemap.xml, que para eso están.

¡Rastrear los enlaces de un sitemap.xml es pan comido!, tiene una complejidad lineal, el ordenador lo hace enseguida.

Mi crawler está codificado en un comando Artisan

Así que ya sabéis por qué he puesto Laravel en mi WordPress. Estoy metiendo herramientas SEO en mi blog, ¿ok?, y tan solo quiero beneficiarme de las características que los frameworks de desarrollo PHP ya tienen implementadas. Quiero ir rápido. Así no tengo que reinventar la rueda una y otra vez cada vez que tengo que poner una característica nueva.

Mi proyecto crawler está todavía en fase de desarrollo pero ya te puedo avanzar que estoy utilizando la capa ORM de Laravel, también tiene validación de formularios y envío de emails, porque para utilizar este crawler tienes que rellenar un formulario donde pones tu email.

Cuando el bot termina de hacer sus cálculos te envía por correo el resultado del rastreo. También tengo en mente añadir una opción de pago para las webs que tienen cientos y cientos de enlaces. Hay páginas web que tienen miles de enlaces…

Los crawlers no son instantáneos, se toman su tiempo para rastrear de forma no intrusiva todos los enlaces de un sitio web. ¿Te imaginas un rastreador de enlaces lanzando varias peticiones HTTP por segundo? ¡Claro que no! Hay que tener cuidado con la frecuencia de rastreo porque el servidor objetivo baneará los bots tan insistentes.

Una araña web puede tardar varios minutos en ejecutarse…

Como decimos, una araña web puede tardar varios minutos en ejecutarse…

Por eso, finalmente implemento mi rastreador de enlaces en un comando Artisan. Los comandos Artisan son muy flexibles porque te permiten instanciar modelos, codificar en OO, mantener la consistencia de tu base de datos, ejecutar lógica de validación, en definitiva, puedes utilizar las características de Laravel que desees en tus comandos Artisan.

También te ayudan a desacoplar la lógica que desees, y sacarla fuera del flujo de ejecución secuencial de PHP.

Ten en cuenta que PHP no es un lenguaje orientado a eventos como Node.js o JavaScript, de modo que una acción de controlador MVC no debe ejecutar directamente la lógica de un rastreador de enlaces porque se quedaría colgada durante el tiempo que tarda en ejecutarse el bot.

La acción de controlador MVC tiene que delegar la ejecución del crawler en el background.

Creacción del comando Artisan

Dicho todo esto, ahora comparto los pasos que he seguido para crear el esqueleto de mi motor de rastreo de enlaces.

Primero ejecuto el comando:

Lo anterior crea automáticamente la clase app/Console/Commands/CrawlSitemap.php. Ahora la edito y actualizo las propiedades $signature:

Y $description:

También actualizo el método handle:

Añado esta entrada al array $commands de app/Console/Kernel.php:

Ya está, ya puedo ejecutar en la consola mi comando Artisan:

De momento este es el esqueleto OO del crawler encapsulado en un comando Artisan.

Es como un “Hola mundo”. Por supuesto que falta codificarlo, pero ahora ya está todo preparado para poderlo ejecutar en el background. Recuerda que PHP no es un lenguaje orientado a eventos como Node.js o JavaScript.

¡Y esto es todo por hoy! De nuevo, muchísimas gracias por leer este post. Dinos si te parece una buena idea meter un crawler web en un comando Artisan codificado con objetos y con patrones de diseño de software. ¿Tiene sentido instalar un framework MVC en WordPress para hacer esto? ¡Deja tu comentario!