Skip to content

Proposition de design alternatif #58

@DavidBruant

Description

@DavidBruant

Description du problème

Cette section ne décrit que ce que j'ai compris du problème. J'invite les lectrice.eur.s à compléter avec ce que je n'ai pas compris

Le Carrefour des Innovations Sociales (CIS) est un moteur de recherche qui recence les projets d'innovations sociales en France
Plutôt que de composer sa base de données ex nihilo, le CIS est composé d'un collectif de partenaires (environ 30 actuellement, nombre en croissance) qui fournissent les données
Plutôt que d'essayer de demander à chaque partenaire sa base de données, puis de travailler à l'uniformiser, la stratégie adoptée par le CIS a été de scrapper les sites des partenaires afin de composer rapidement le moteur de recherche
Afin que le moteur de recherche soit à jour, le scraper doit être lancé régulièrement automatiquement

OpenScraper se veut être le morceau de la solution qui va chercher les données chez les partenaires et les uniformise avant traitement puis affichage

Description de la solution actuelle

OpenScraper contient un client et un serveur
Le serveur stocke dans une base de données MongoDB :

  • le modèle de données (unique par instance d'OpenScraper) que l'on souhaite récupérer des scrapings
  • la configuration des "contributor" (ou "spider"), qui consiste en un ensemble de xpath pour cibler les données dans les pages et quelques autres informations
  • les données scrappées

Le serveur fait aussi tourner le scraper

Le client n'est qu'une interface utilisateur qui rend plus agréable de configurer open scraper, décider quand lancer un scrapping, prévisualiser le résultat, mais n'a pas de code "intelligent"

Singularités

OpenScraper hardcode l'idée que l'on sera toujours dans une des deux configurations :

  • toutes les informations du projet sont dans une page listing
  • toutes les informations du projet sont dans une page à suivre après la page listing

Les Xpath fournis sont appliqués à la fois sur la "page listing" et la "page projet", donc les données sont mélangées si les XPath s'appliquent dans les deux cas (comme dans le site de Coorace)

Les mêmes Xpath sont appliqués à toutes les pages sans exceptions possibles

Une spider est un document dans une base de données Mongo
Entre autres choses, cela signifie qu'elle est dépendante d'une version d'OpenScraper et aussi qu'elle n'est pas versionnée par défaut (contrairement à si la spider était un fichier de code Python ou autre)
Le code des spider est unique et stocké dans masterspider.py (actuellement ~1400 lignes de code)

Process de création et modification de spider

  1. Créer une version locale d'open scraper
  2. Créer le même modèle de données qu'en production (manuel) (une seule fois)
  3. Configurer la spider
  4. Tester jusqu'à être satisfait du résultat
    1. Modifier les XPath
    2. Changer le code d'OpenScraper (masterspider.py) si le site ne correspond pas aux pré-supposés hardcodés
    3. Lancer la spider "en mode test"
    4. Lancer la spider "pour de vrai"
  5. Copier la spider en production (manuel)

Pour la modification, pareil que le process de création à part que 3 est une copie manuelle de la version en production

Dans les deux cas, le gros du temps est passé dans l'étape 4

Dangers associés à utiliser le même code pour toutes les spiders

L'étape 4.2 n'est pas systématique, mais est nécessaire dès que l'on cherche à scrapper un site qui ne correspond pas aux pré-supposés du fichier masterspider.py. Cela arrive toutefois assez régulièrement et il est impossible de prévoir quel nouveau site va nécessiter de modifier à nouveau masterspider.py

Chaque nouveau cas est souvent résolu par l'ajout d'une nouvelle option dans l'interface de configuration de la spider. La liste des options est condamnée à ne faire que croître sans que personne ne puisse savoir jusque quand, car enlever une option pourrait casser une spider dépendant de cette option

De par le fait que masterspider.py est le même code utilisé pour toutes les spiders, le modifier est un exercice périlleux, car le modifier pour faire marcher une spider comporte le risque de casser une ou plusieurs autres spiders. Ce risque pourrait être réduit par la présence de tests automatisés, mais il n'y en a actuellement aucun

A noter que ce risque pèse sur l'instance du Carrefour des Innovations Sociales, mais pèse sur toutes les instances futures d'OpenScraper : il est possible que dans une future version d'OpenScraper, masterspider.py soit modifié d'une manière qui casse les spiders de l'instance

Aucun retour direct sur les erreurs durant le scrap

L'étape 4.3 est actuellement assez difficile, car beaucoup d'erreurs sont possibles, mais l'outil ne les fait pas remonter facilement. Erreurs possibles :

  • XPath non-valide
  • XPath qui ne matche aucun élément sur une page (sur toutes les pages ou sur une certaine page)
  • Données récupérées non-valides par rapport à un format attendu (par exemple, une adresse postale qui contiendrait le symbole )
  • URLs qui ne fonctionnent pas (404, 403, 500, boucle de redirect infinis, etc.)

On ne se rend compte de ces erreurs que dans des messages dans la console (qui contient beaucoup de messages) ou en constatant que nos attentes ne sont pas satisfaites en inspectant les données récupérées manuellement
Ce process est aussi limité, surtout quand le scrapper ramène des centaines ou milliers de résultats

Pourtant ces erreurs arrivent avec des causes diverses :

  • être humain
  • redesign de site
  • cas particuliers

Ces causes sont fréquentes. Même les redesign. Si on imagine qu'un site procède à un redesign tous les 5 ans, alors en moyenne, sur 30 partenaires, l'un d'eux fait un redesign tous les 2 mois. Il est donc fréquent de devoir réécrire des spiders cassées pour redesign

Aussi, en relançant la spider régulièrement, il sera découvert des nouvelles pages qui ne correspondent parfois pas aux attentes de la spider

Aujourd'hui la boucle de feedback d'essayer des XPath, de constater que quelque chose ne va pas, de comprendre pourquoi avant de réessayer est un processus très manuel et long
Le problème ne va être que plus visible et douloureux quand il va s'agir de laisser OpenScraper tourner tout seul pour se mettre à jour automatiquement

Description d'une autre solution possible

Spider en tant que code

Si chaque spider était son propre fichier de code, elle pourrait être versionnée (donc avoir l'histoire des changements), n'avoir qu'une faible dépendance au cœur d'OpenScraper (ou une dépendance forte, mais choisie et non imposée comme actuellement). Elle serait moins fragile aux changements d'OpenScraper. Le cœur d'OpenScraper pourrait être beaucoup plus petit et donc plus facile à maintenir
Chaque spider pourrait aussi être facilement testée par des tests automatisés
Copier une spider ne serait plus un jeu de copier/coller entre la prod et le dév, mais juste un git push et un git pull

Cette approche aurait un bonus supplémentaire pour les instances qui souhaitent être open source qui pourraient partager leur code contrairement à l'approche actuelle où la configuration de la spider et ses XPath est cachée dans une base de donnée MongoDB

Chemin de transition pour le Carrefour des Innovations Sociales

  • Garder masterspider.py pour le moment
  • Pour chaque spider :
    • Télécharger en tant que fichier JSON la configuration et la versionner
    • Créer un fichier de code qui se résume à appeler masterspider.py avec la configuration JSON
  • Le modèle devient une classe ou interface Python

Quand une nouvelle spider est à créer, la créer "de zéro"
Quand une spider est à refaire, réécrire le code "de zéro" sans utiliser masterspider.py

"de zéro" est mis entre guillemet, car il est ok dans ce cas-là de copier/coller du code, par exemple de masterspider.py, en le nettoyant pour ne garder que les morceau utile à ce site spécifique
S'il est nécessaire de traiter un cas non-prévu par l'actuel masterspider.py, le.a développeur.euse aura accès à tout Python pour le faire

OpenScraper pourra fournir des classes et fonctions qui facilitent la vie d'écriture de spider. L'utilisation de ces fonctions et classes dans une spider sera optionnel

Assistance d'OpenScraper dans la gestion des erreurs

A chaque fois que l'on fait tourner une spider ("en test" ou "en vrai"), il s'agit d'un run. Il serait possible qu'OpenScraper, pour chaque run, stocke toute l'activité utile :

  • Toutes les URLs visitées, leur code de retour, (le corps de la réponse HTTP si ça pèse pas trop lourd ?)
  • Les chemins de navigations
  • les XPath (ou sélecteurs CSS ou toute autre forme de sélection/query) essayés sur quelles pages, s'ils sont valides, si elles n'ont rien retourné, si ce qui est retourné est conforme à des attentes fournies
    • les attentes peuvent être fournies à la définition du modèle en tant que classe Python
  • Toute autre information utile à la reproductibilité manuelle d'une erreur constatée

OpenScraper pourrait contenir un écran qui affiche les résultats d'un run en mettant en avant les erreurs rencontrées

Pour les erreurs de contenu qui ne se conforme pas aux attentes, il pourrait être possible de manuellement accepter (un par un ou par groupe) que les contenus soient publiés

Si trop d'erreurs sont rencontrées, les données récupérées dans le run sont mises dans un espace temporaires et ne sont pas publiées. Une revue humaine est nécessaire pour validation. L'intervention d'un.e développeur.euse est peut-être nécessaire

Chemin de transition pour le Carrefour des Innovations Sociales

Rien de spécial, il s'agit d'une nouvelle fonctionnalité qui peut être ajoutée en complément du design actuel

Piste alternative et complémentaire

Plutôt que d'essayer de demander à chaque partenaire sa base de données, puis de travailler à l'uniformiser, la stratégie adoptée par le CIS a été de scrapper les sites des partenaires afin de composer rapidement le moteur de recherche

Au vu du travail conséquent que demande de maintenir OpenScraper et les spiders, rencontrer les partenaires pour voir si une solution alternative au scrapping est possible est peut-être une bonne piste
Cette piste peut être menée en parallèle d'un redesign d'OpenScraper

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions