La Lanterne Rouge

Warning: Geek Inside

Phrawler : encore un crawler

- Posted in Sans catégorie by

TL;DR; Phrawler est un webcrawler simple codé en PHP avec appels non-bloquants pour améliorer les performances. Le dépôt Git est ici : https://codeberg.org/nanawel/phrawler


Vous ne le saviez pas, mais il manquait encore un outil de crawling HTTP. Si si.

OK, en fait probablement pas mais :

  • d'un j'ai pas trouvé ce que je cherchais
  • et de deux ça m'amusait de remettre les pattes dans AMPHP dans ce contexte, pour voir si ça pouvait donner un résultat intéressant et performant

J'utilisais il y a quelques années crowl qui faisait bien le taf, à savoir parcourir un site donné et indexer dans une base de données MySQL chaque page trouvée, avec les informations d'intérêt (taille, temps de réponse, code de réponse, etc.). C'était ensuite super pratique d'avoir la puissance du SQL pour chercher des données et faire des stats pour savoir où se concentrer (codes d'erreur, temps de latence, etc.).

Mais voilà même si j'avais dockerifié l'application parce que... "Python", ben même la version dockerifiée ne veut plus se builder correctement. Les joies de ce langage... 😡 (oui c'est la tradition, les pythonistes crachent sur les phpistes et inversement, c'est comme ça depuis la nuit des temps aucune raison de changer).

Bref.

Comme pour chaque besoin similaire on part sur une base de Symfony console, et on ajoute les packages AMPHP nécessaires.

Dans mon cas, ce qui m'intéresse c'est de rendre principalement les appels HTTP non-bloquants. De cette manière je me dis que pendant qu'une requête est en cours, on peut en démarrer une autre et ainsi de suite, et quand la réponse est revenue on la traite mais on n'a pas de temps mort obligatoire à attendre sur des I/O. Dans le même ordre d'idée on appliquera la même gestion aux écritures sur disque : logs, base de données, etc. (même si c'est dans une moindre mesure en comparaison des requêtes HTTP qui seront faites et qui seront assurément le goulet d'étranglement).

Pour la partie client HTTP il y a un package dédié : https://amphp.org/http-client

Pour l'écriture dans un fichier de log (style pseudo-CSV, ce que je fais aussi) c'est pareil : https://amphp.org/file

Pour SQLite par contre, rien n'existe à ce jour. C'est dommage.

Pour MySQL (ou plutôt MariaDB de préférence), je suis parti avec https://amphp.org/mysql qui était là pour ça, mais après de longues et chiantes séances de tests il manquait toujours des données à la fin de l'exécution, et je voyais dans les logs du serveur des erreurs de communication. J'en ai conclu que cette lib n'était pas très au point pour l'instant, donc je me suis rabattu sur du bon vieux PDO, en sacrifiant évidemment les capacités "asynchrones" (plutôt non-bloquantes).

Point très intéressant par contre : un générateur de fichier HAR existe nativement dans amphp/http-client, ce qui fait un bonus très appréciable pour un crawler si on veut pouvoir afficher ensuite le rapport détaillé dans un des nombreux viewers qui existent.

Après quelques premières versions un peu approximatives mais qui m'ont permis de valider le principe et de le tester pour un besoin pro, j'ai affiné petit à petit l'implémentation. Elle reste assez artisanale, je vais pas non plus faire un truc méga-chiadé pour un outil si petit, mais ça marche, c'est propre, performant et ça permet de générer des crawls et des rapports sous plusieurs formes, dont un en base de données qui peut être ensuite utilisée comme source dans un outil comme... Grafana bien sûr. 🤩

Démo rapide avec podman

Mieux, avec l'image Docker (compatible Podman) on peut l'exécuter depuis un fichier docker-compose.yml avec des variables d'environnements qui permettent de configurer l'exécution aux petits oignons, et les croner régulièrement pour avoir des métriques historisées dans une base et faire de jolis graphiques d'évolution.

Bon les données de la capture sont pas les plus sexys mais c'était pour l'exemple.

Il reste probablement des fonctionnalités à ajouter et pas mal de refacto à faire pour que ça soit un peu plus propre, mais en l'état c'est déjà pas mal et ça comble totalement le besoin que je remplissais auparavant avec Crowl. Je vais donc probablement passer ce petit projet en maintenance légère et chercher un nouveau jouet à bidouiller.

Le code est hébergé sur Codeberg1 : https://codeberg.org/nanawel/phrawler

Et les images Docker dispo sur le hub officiel : https://hub.docker.com/r/nanawel/phrawler


  1. La migration de mes projets depuis Github est en cours. Par principe et parce que j'en ai les moyens, je préfère les héberger sur une plateforme plus éthique et que je soutiens directement par des dons réguliers. ↩︎

Comments