Comment faire un sondage simple ?

Auteurice : Arthur Pons

Temps de lecture : ~9 minutes


J’ai eu besoin à plusieurs reprises de construire des sondages très simples pour des associations. Si l’on souhaite minimiser le recours au numérique il est toujours bon de se rappeler qu’il existe des moyens analogiques de sonder un groupe de personne. D’expérience il est considéré utile voir nécessaire d’avoir recours au numérique quand les personnes à sonder sont dispersées géographiquement et temporellement.

Explorons la possibilité de faire des sondages à l’implémentation et l’utilisation plus simple que google forms, framaforms etc.

Par mail

Il est possible de créer des sondages par mail. L’idée est décrite en détail dans l’article sur kun. Ce système a des avantages et des désavantages.

Parmi les désavantages on peut noter un potentiel souci d’intégrité des données si les personnes répondant au sondage modifient (par accident ou par malveillance) les propositions de réponses envoyées dans le mail.

Second désavantage, il est délicat de créer des types de questions autres qu’à choix multiples autrement qu’en écrivant dans le corps du mail quelque chose du type

Quel est votre couleur préférée ?
ne retenir qu'une seule des deux propositions suivantes

bleu
rouge

ce qui, à moins de sonder des personnes particulièrement attentives et disciplinées, conduira forcément à des soucis d’intégrité. Ces soucis pourraient être assez facilement identifiés en vérifiant si une réponse contient à la fois la réponse bleu et rouge mais cela ne dit rien sur la façon de corriger l’ambigüité. Il serait nécessaire de resonder la personne. C’est pourquoi cette solution via mail fonctionne pour des choix de dates mais pas pour la plupart des types de sondages.

Via les log de serveur web

Oui oui vous avez bien lu le titre, on peut sonder des personnes en leur faisant construire une url précise. On récolte ensuite les informations en parsant les logs du serveur.

Marc Chantreux avait pratiqué cette technique en septembre 2022 en envoyant ce mail à la liste devlog.

D’après vous donc quelle est la tendance majoritaire au sein de votre organisation? Merci de bien vouloir me répondre sous la forme N,P,D,F,H,X,O,E décrite ci après. la réponse peut être multiple. par exemple dans mon cas:

debian,tech,desktop,5,5,,u-strasbourg-dnum,mc@unistra.fr scientific-linux,chercheur,cluster,0,,+500,u-strasbourg

que j’interprète tel que:

les critères sont:

N: nom de l’OS les distros linux comptent pour OS P: population exemples: dev, tech, chercheur, étudiant, admin (personnels administratifs) D: device ( exemples: cluster (hpc), desktop, tablette, smartphone F: free (de 1 à 5) à quel point ce choix a été consenti par les usagers (5 étant un choix total de sa part). H: happy (de 1 à 5) à quel point l’usager témoigne sa satisfaction par rapport à la dis X: nombre approximatif d’utilisateurs (si connu) O: votre organisation E: votre adresse de contact si vous souhaitez être recontacté

N’ayant pas le temps de créer ou utiliser un outils de sondage, je vous propose un “sondage par log”: merci de construire (dans votre navigateur ou avec curl) l’adresse suivante (qui répondra 404 et c’est normal).

https://people.u-strasbg.fr/surveydistro/devlog2209/N,P,D,F,H,X,O,E

par exemple: j’aurais tendance à répondre au sondage comme suit:

set https://people.u-strasbg.fr/surveydistro/devlog2209 <<. xargs -d”\n” -IX curl -k $1/X debian,tech,desktop,5,5,,u-strasbourg-dnum,mc@unistra.fr scientific-linux,chercheur,cluster,0,,+500,u-strasbourg

Au pire n’hésitez pas à m’envoyer votre retour par mail (tsv, csv, attachement: je m’en débrouillerais et vous remercie par avance pour toute réponse).

Le code écrit dans le mail construit les deux commandes suivantes :

curl -k https://people.u-strasbg.fr/surveydistro/devlog2209/debian,tech,desktop,5,5,,u-strasbourg-dnum,mc@unistra.fr
curl -k https://people.u-strasbg.fr/surveydistro/devlog2209/scientific-linux,chercheur,cluster,0,,+500,u-strasbourg

L’accès à ces urls ne feront strictement rien d’autre sur le serveur web que d’ajouter une ligne dans les logs. On peut ensuite parser les logs comme on le souhaite pour générer un fichier csv ne content que les réponses sous la forme :

debian,tech,desktop,5,5,,u-strasbourg-dnum,mc@unistra.fr
scientific-linux,chercheur,cluster,0,,+500,u-strasbourg

Le gros désavantage de cette technique est qu’il est très facile pour quelqu’un de spammer les réponses. Si la personne le fait derrière la même ip on peut le filtrer assez rapidement mais si elle possède plusieurs ip différentes elle peut influencer le sondage.

Ce genre de soucis sont relativement anecdotiques quand on sonde une cohorte limitée et connue de personnes1. C’est pourquoi il n’est pas forcément nécessaire d’avoir recours à des outils compliqués dans un bon nombre de cas.

Via formulaire html et CGI

Pour partiellement remédier aux problèmes précedemment évoqués nous pouvons avoir recours à un formulaire web et un cgi pour parser les réponses.

Si l’on reprend l’exemple précédent, la question “A quel point ce choix a été consenti par les usagers ?” prend pour valeur un entier entre 1 et 5 mais il n’y a aucun moyen de vérifier si c’est bien le cas de la donnée insérée dans l’url. En utilisant des formulaires html et des balises d’input on peut contrôler l’intégrité des données à la saisie2.

La collecte de données

Prenons pour exemple le formulaire html suivant :

<form action="/cgi-bin/parse.cgi" method=post enctype=multipart/form-data>
    <fieldset>
        <legend>Récolte</legend>
        <label for="daterecolte">Date</label>
        <input type="datetime-local" name="daterecolte" id="date" required/>
        </br>
        <label for="emplacement">Emplacement</label>
        <select name="emplacement" id="emplacement" required/>
            <option value='grand-brezouard'>Grand Brézouard</option>
            <option value='champ-du-diable'>Champ du Diable</option>
            <option value='abris-fuste'>Abris Fuste</option>
            <option value='petit-brezouard'>Petit Brézouard</option>
        </select>
    </fieldset>
    <fieldset>
        <legend>Neige</legend>
        <label for="hauteur">hauteur (cm)</label>
        <input type="number" name="hauteur" id="hauteur" min="0" max="100" step="0.1" value="0" size="3" required/>
        <span>cm</span>
    </fieldset>
    <fieldset>
        <legend>Météo</legend>
        <label for="tempmoy">température moyenne</label>
        <input type="number" name="moyenne" id="tempmoy" min="-30" max="50" step="0.1" value="15" size="3" required/>
        <span>°C</span>
        <label for="pression">Pression atmosphérique (hPa)</label>
        <input type="number" name="pression" id="pression" min="800" max="1500" step="0.01" value="1013.25" required/>
        <span class="validity"></span>
    </fieldset>
    <fieldset>
        <legend>Remarques</legend>
        <textarea id="commentaire" name="commentaire" rows="4" cols="50" placeholder="Comentaire..."></textarea>
    </fieldset>
    <p>
    <button type="submit">Soumettre les informations</button>
    </p>
    <input type="reset" value="Réinitialiser">
</form>

On y retrouve quelques exemples d’input. On peut par exemple contrôler les valeurs possibles pour la hauteur de neige avec les directives min, max et step. On peut aussi noter certains input comme nécessaires avec required.

Quand la personne sondée appuie sur le bouton soumettre, le script qui se trouve à /cgi-bin/parse.cgi sera exécuté et recevra dans stdin les données du formulaire. Si l’on veut récupérer les données sous la forme d’un csv il faut faire tourner quelques moulinettes. J’ai découvert avec beaucoup d’étonnement que le texte généré par le formulaire post varie d’un navigateur à un autre. Je sais donc uniquement que mon code fonctionne avec ma version de Firefox et de Chromium.

Les grandes étapes du script sont de récupérer le contenu :

POST_STRING=$(cat)

La commande pour récupérer la valeur d’une question en se basant sur l’id de la balise html correspondante :

recuperervaleur() {
    echo $POST_STRING | sed -n "/name=\"$1\"/,/------/ p" | grep -v "Contennt-\|------\|^ \|^$"
}

La boucle pour aller toutes les chercher

for i in  daterecolte emplacement hauteur moyenne pression commentaire
do
    if [ $i = "commentaire" ]
    then
        if [ ! $(echo $data | grep -q "commentaire") ]
        then
            recuperervaleur $i | sed -z 's/\n/\\n/g;s/  /    /g' | sed 's/\\n$/\n/' >> $temp
        else
            echo "" >> $temp
        fi
    else
        recuperervaleur $i >> $temp
    fi
done

La boucle traite différemment le champ commentaire pour remplacer les retours à la ligne par \n histoire de pouvoir les stocker en TSV sur une seule ligne. Elle ajoute les valeurs dans un fichier temporaire temp. On traite ensuite ce fichier pour en faire un TSV dans un fichier nommé res :

cat $temp | tr '\n' '   ' | sed 's/ $/\n/' >> res

Vous devriez pouvoir assez facilement adapter ce code pour vos besoins. Par exemple, si le fichier res est gité, on peut finir le script en faisant un commit et ainsi enregistrer l’historique de toutes les réponses au sondage.

Présenter les résultats

Un avantage d’avoir un serveur web est que l’on peut publier les résultats assez facilement, y compris en temps réel. Si l’on a dans un fichier TSV les données suivantes :

a   b   d   g   h   e   q
a   c   d   g   e   r   t   f
r   t   c   d   a   f   b
e   a   c   g   e   d   f   v   b

On peut avoir des statistiques de base sur l’occurence de chaque réponse en faisant

tr '    ' '\n' data | sort | uniq -c | sort -nr
  4 e
  4 d
  4 a
  3 g
  3 f
  3 c
  3 b
  2 t
  2 r
  1 v
  1 q
  1 h

Si la première colonne est une question donnée et que l’on veut étudier les réponses sur cette question en particulier on peut remplacer le tr par un simple cut

<<. cut -f1 | sort | uniq -c | sort -nr
  2 a
  1 r
  1 e

Pour tout ce qui est des inputs radio et checkbox si vous voulez qu’apparaissent non pas les identifiants des balises mais le contenu mis dans la balise <label> vous pouvez utiliser la fonction suivante :

idtolabel() {
    xargs -d'\n' -n1 sh -c 'grep "\"$1\"" 'fichier.html'' -- |
    grep "label" |
    sed -E 's:<[^>]*>::g;s:^    *::g' |
    tr -d '<>
}

à laquelle il faut passer les identifiants en argument.

Pour afficher les sorties de toutes ces commandes le plus simplement possible vous pouvez ajouter en début de script

<<% cat
<meta charset="utf-8">
<pre>
%

et à la fin fermer la balise pre

echo "</pre>"

Commentaires divers

L’esprit de ce système combiné à Kun et respl est en cours de développement pour avoir une interface web simple3. Il faut noter qu’utiliser ce genre de systèmes avec alimentation d’un fichier texte contenant les résultats sur un serveur a l’avantage d’être très flexible. Si l’on créé une interface web, elle n’empêche pas “d’attaquer” le fichier texte autrement4. Si à Katzele nous privilégions certaines interfaces pour des raisons mille fois évoquées, nous souhaitons avant tout faire en sorte que les services soient les plus inclusifs possible en utilisant des dénominateurs techniques sobres mais extensibles.

Trois formulaires ont déja été créés et utilisés avec ce système avec succès. Il sera utilisé dans le cadre d’un projet de recherche participatif mené conjointement par l’EOST et la Jardin des Sciences de l’Université de Strasbourg. Il semble assez fiable et assez robuste pour des usages légers ne nécessitant pas des sondages complexes5 ou des fonctionnalités avancées type sauvegarde d’une réponse en cours de remplissage etc. Il est tout de même possible de conditionner l’accès au formulaire via un système d’authentification type HTTP_BASIC et éventuellement un petit contrôle si la personne authentifiée a déjà soumis une réponse.

Dans les sondages menés à bien les formulaire n’avaient pas de css et il n’y a pas eu de soucis particulier à leurs remplissages. Les personnes sondées étaient de niveaux techniques très divers mais toutes relativement jeunes.

Le plus ennuyant est d’écrire le formulaire html. Peut-être que cela pourrait être amélioré en produisant un petit moteur de génération de formulaire. Il est possible que ce soit un problème bien plus complexe qu’il n’y paraît et que ce soit du temps perdu ou le première marche vers une complexification abusive du système. Je pense tout de même faire un petit test un jour. Dans tous les cas si le moteur n’est pas satisfaisant cela n’empêche pas d’écrire de l’html à la main.


  1. typiquement une association dans laquelle on connait les personnes et la quantité de réponses attendues. 

  2. côté client uniquement donc cela reste assez limité 

  3. l’implémentation sera certainement très différente mais ce n’est pas bien important, il y a tellement peu de code derrière tout cela. L’esprit compte, le texte moins. 

  4. en ssh directement, via un mail + une nouvelle moulinette, via un dépôt git sur le fichier est gité etc. 

  5. je pense notamment à l’idée de conditionner l’apparition de questions aux réponses données à d’autres questions. Remarque ça doit être possible avec du css, à tester.