Listes twitter et élections fédérales 2015

À l’occasion des élections fédérales 2015 qui se préparent sur Twitter (suivez le hashtag #EF2015), il est bon d’affuter ses outils ou d’en fournir à d’autres à qui ils pourraient être utiles.

J’ai essayé de rafraîchir un peu ma connaissance de Tweepy et de l’API twitter. Si cette phrase vous fait peur, pas de panique! Je vais essayer de vous expliquer de quoi il s’agit. Vous n’avez pas besoin d’être capable de le faire vous-même, mais cela pourrait vous donner des idées pour demander un développement au programmeur que vous avez sous la main (ou à moi).

Je vous propose 3 outils très simples que j’ai rapidement réalisés pour des tests:

  1. un script qui ajoute les membres d’une liste publique quelconque à une de mes listes: idéal pour repartir d’une liste existante ne m’appartenant pas et que je souhaite modifier
  2. un script qui compare 2 listes publiques quelconques (et qui me dit qui est dans une, dans l’autre et dans les deux)
  3. un script qui liste tous les membres d’une série de listes et qui les mets tous dans une de mes listes: idéal pour créer une mégaliste EF2015

Début commun du script

Pour effectuer des requêtes et écrire dans Twitter, il faut disposer de Python, de Tweepy et d’une application Twitter. Cette application donne des clés (mots de passe d’identification) qui permettront de travailler. Les trois scripts que je propose ici commencent de la même manière:

# -*- coding: utf-8 -*-

# L'outil magique
# http://www.tweepy.org/
import tweepy

# Il faut créer une application twitter
# https://apps.twitter.com/
consumer_key = "(Ejdos98em"
consumer_secret = "S)NW)SLNnw00rjd"

access_token = "23490871234bnklawsiodsasdfnkl"
access_token_secret = "sadfpoiasdfoijasnmasdéfoijasdfé"

# Le propriétaire de l'app (= en principe, vous ;) )
owner = "NicolasFriedli"

# Processus d'authenficication
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
api = tweepy.API(auth)

Vous devez créer votre application à l’adresse indiquée et  remplir les 4 clés utiles (avec droits en lecture et écriture). À la fin de ce processus, votre script est prêt à passer à l’action et c’est là que ça devient intéressant.

Ajouter des twittos à une de mes listes

On commence par poser des questions:

  • quelle est le nom de la liste dont je dois copier les twittos?
  • à qui appartient cette liste?
  • dans laquelle de mes listes je vais les ajouter?
    NB: on ne copier pas une liste ici, on ajoute!

Puis on crée une liste vide.

# La liste dont on aimerait ajouter les membres à une de ses listes
list = raw_input('Liste à ajouter: ')

# Le nom du propriétaire de la liste externe
user = raw_input('Proprio de la liste: ')

# Liste à laquelle ajouter les twittos
# Cette liste doit m'appartenir et exister!
my_list = raw_input('Ajouter à ma liste: ')

# On va ajouter tous les twittos en une fois, 
# on les stocke dans une liste.
# Pas de contrôle des doublons, il faudrait un set...
complete_list=[]

Maintenant que l’on a toutes les données, on passe au script à proprement parler. On liste tous les membres de la liste choisie, puis on ajoute tout dans ma liste.

# On utilise Cursor pour parcourir toute la liste 
# (avec 5000, nécessaire?)
# On ajoute le nom du twitto à la liste temporaire
for member in tweepy.Cursor(api.list_members, user, list, count=5000).items():
    complete_list.append(member.screen_name)

# On envoie la liste complète à l'API twitter
api.add_list_members(slug=my_list, owner_screen_name="NicolasFriedli",screen_name=complete_list)

Et c’est tout 😉 Pas besoin de vous expliquer l’utilité de la chose.

Comparer 2 listes

Même début, puis on pose les questions:

# La liste dont on aimerait ajouter les membres à une de ses listes
list1 = raw_input('Première liste: ')

# Le nom du propriétaire de la liste externe
user1 = raw_input('Proprio première liste: ')

# La liste dont on aimerait ajouter les membres à une de ses listes
list2 = raw_input('Seconde liste: ')

# Le nom du propriétaire de la liste externe
user2 = raw_input('Proprio seconde liste: ')

Une fois les noms des listes (et proprios) connus, on passe à l’action. J’ai volontairement doublé la commande pour rester dans la mentalité script, sans déclarer de fonctions (les puristes hurleront, mais je m’en fiche un peu).

Donc, on crée deux «listes» (les puristes hurleront encore, et je reste sourd à leurs complaintes: ce sont des sets) vides. Puis on les remplit des noms des twittos:

l1 = set()
l2 = set()

# On utilise Cursor pour parcourir toute la liste (avec 5000, nécessaire?)
# On ajoute le nom du twitto à la liste temporaire
for member in tweepy.Cursor(api.list_members, user1, list1, count=5000).items():
    l1.add(member.screen_name)

for member in tweepy.Cursor(api.list_members, user2, list2, count=5000).items():
    l2.add(member.screen_name)

Et à la fin, on analyse:

  • un résumé:
    • nombre de twittos dans chaque liste
    • nombre de twittos dans une liste mais pas dans l’autre
    • nombre twittos communes
  • et des détails
    • liste des twittos dans une liste seulement
    • liste des twittos dans l’autre liste seulement
    • liste des twittos communs
# Analyse

print "*****"

print "La liste %s (appartenant à %s) compte %s twittos. " % (list1, user1, len(l1))
print "La liste %s (appartenant à %s) compte %s twittos.\n " % (list2, user2, len(l2))

print "%s twittos appartiennent à la liste %s (%s) seulement." % (len(l1 - l2),list1, user1)
print "%s twittos appartiennent à la liste %s (%s) seulement.\n" % (len(l2 - l1),list2, user2)

print "%s twittos appartiennent aux deux listes.\n" % len(l1 & l2)

print "Dans la liste %s (appartenant à %s) seulement: " % (list1, user1)
for u in l1 - l2:
    print u

print "\n*****"
    
print "Dans la liste %s (appartenant à %s) seulement: " % (list2, user2)
for u in l2 - l1:
    print u

print "\n*****"

print "Dans les deux listes:\n"
for u in l1 & l2:
    print u
    
print "\n*****"

Et c’est tout? Oui, c’est tout 😉

Le résultat (listes raccourcies):

nicolas@hector:~/Bureau/tweepy$ python compare_lists.py 
Première liste: kandidatinnen-ständerat
Proprio première liste: wahlch15
Seconde liste: ne-ws
Proprio seconde liste: LFBerset
*****
La liste kandidatinnen-ständerat (appartenant à wahlch15) compte 22 twittos. 
La liste ne-ws (appartenant à LFBerset) compte 72 twittos.
 
21 twittos appartiennent à la liste kandidatinnen-ständerat (wahlch15) seulement.
71 twittos appartiennent à la liste ne-ws (LFBerset) seulement.

1 twittos appartiennent aux deux listes.

Dans la liste kandidatinnen-ständerat (appartenant à wahlch15) seulement: 
Juerg_Grossen
ThBurgener
Pierre_Castella
...
beatflach
RuediNoser
HenselerN

*****
Dans la liste ne-ws (appartenant à LFBerset) seulement: 
hoffertdavid
JospinLa
Vrublux
A_deMontmollin
...
Matthieu_Aubert
JulienHirt1
UniNeuchatel

*****
Dans les deux listes:

mauro_moruzzi

*****
nicolas@hector:~/Bureau/tweepy$ 

Compilation de listes

Bon, ça, c’est le truc que je préfère. L’idée est simple:

  • dans un fichier CSV, éditable par n’importe quel débutant, on nomme toutes les listes que l’on aimerait compiler (proprio dans une colonne, nom de la liste dans l’autre)
  • ensuite, on envoie le script qui ajoute toute le monde dans ma liste, qui pourrait s’appeller mega-ef2015 par exemple

Comme on va jouer avec du CSV, il y aura ceci dans le script

import csv 

...

data = csv.reader(open("megaliste.csv", "r"))

Puis, dans le script, il y aura ceci:

# Le propriétaire de l'app (= en principe, vous ;) )
owner = "NicolasFriedli"
final_list ="mega-ef2015"

l = set()

for d in data:
    for member in tweepy.Cursor(api.list_members, d[0], d[1], count=5000).items():
        l.add(member.screen_name)

# On envoie la liste complète à l'API twitter
api.add_list_members(slug=final_list, owner_screen_name=owner,screen_name=l)

Je précise un truc. Comme ma liste est un set, il ne peut y avoir qu’une seule fois la même valeur. Donc, je me fiche un peu qu’un twitto se trouve dans 1, 2 ou 10 listes. Au final, on n’enverra qu’une fois chaque nom quand on demandera à ajouter du monde (ce qui limite les accès à l’API).

Et c’est tout?

Oui.

Vous avez compris ce que l’on peut imaginer, surtout si l’on combine les outils. Par exemple, j’ajoute un candidat aux élections fédérales dans ma liste de veille seulement s’il se trouve à la fois dans la liste maintenue par la RTS et celle maintenue par la NZZ… Et, une fois par semaine, je relance le script qui me met tout à jour 😉

Si ça vous intéresse d’aller plus loin, dites-le moi! On pourrait créer un GitHub de scripts utiles (le voici: TwitterEF2015). Ou alors je peux vous créer un script (voire un programme, avec des vraies fonctions def) pour un usage précis.

Pétition pour Uber à Genève (ou les URL expliquées)

Actuellement en cours, une campagne intitulée NON à l’interdiction d’Uber à Genève! Pas besoin d’allonger sur ce que j’en pense: le monde nouveau qui bouscule un monde ancien qui ne veut (ou ne peut) pas changer. Puis la politique s’en mêle…

Ce qui m’intéresse ici, c’est l’URL de la campagne que l’on va disséquer. L’adresse complète est https://action.uber.org/geneve/:

  • https
    Signifie que c’est une adresse sécurisée, c’est très bien puisque c’est une pétition et que transitent des données. Je ne développe pas.
  • uber.org
    Je trouve cela intéressant: Uber a installé son propre système de pétition, sur son propre nom de domaine. Pas d’utilisation d’un système en ligne existant. Cela rend la campagne impossible à fermer (et démontre une compréhension du web et de certains de ces enjeux…).
  • geneve
    Tiens, tiens, la mention de la ville est une répertoire. Est-ce que cela pourrait signifier que ce n’est pas une campagne isolée? Si une seule campagne était en cours, l’adresse serait peut-être https://action.uber.org/.
  • action
    Donc, tout cela est installé dans un sous-domaine. Si je lis bien l’URL complète de la pétition pour Genève, j’en déduis que toutes les pétitions se trouvent dans le sous-domaine action, et que chaque pétition a son propre répertoire.

Je pourrais donc essayer l’adresse https://action.uber.org/ pour arriver au «départ» des pétitions et espérer les lister toutes. Et là… rien! Renvoi sur la page d’accueil (au moins, ce n’est pas un répertoire libre de lecture ou une erreur 404).

Mais vous savez que j’aime beaucoup les recherches Google. Allons-y, c’est trivial! Recherchez (résultat):

site:action.uber.org

Environ 50 résultats. Environ 50 campagnes en cours, majoritairement en anglais, mais aussi en français et en espagnol, concernant des villes du monde entier, parfois pour soutenir l’arrivée d’Uber, parfois pour défendre Uber quant il est attaqué.

Dans le domaine de la communication, de l’engagement des citoyens et des moyens de faire pression aussi, on change de monde!

 

Logos R du jubilé de la Réforme 2017 personnalisés

À l’occasion du Jubilé de la Réforme en 2017, la FEPS a eu la bonne idée de créer une vraie charte graphique, un logo officiel, etc. Mais, surtout, la FEPS propose de créer des logos personnalisés. Les explications sont claires, mais pas toujours évidentes à suivre. Voici ce que je vous propose.

SEK_FR_Logo_RGB
Le logo officiel en français.

Vous trouverez toutes les informations sur l’utilisation des logos officiels et la création de logos déclinés sur une page spécifique. Je vous conseille de la lire intégralement, ainsi que les deux documents pdf (Guide et Règles).

Calque pour un logo personnalisé

C’est dans le guide que nous trouvons les informations utiles pour la création d’un logo personnalisé:

  • page 9: des exemples de logos pour nous expliquer ce qui est permis (contrastes, couleurs, fond, etc.)
  • page 8: des normes pour les marges (du logo officiel)

En respectant ces règles de marges (les 4 marges sont égales, avec pour valeur la moitié de la largeur du R), on obtient une image qui pourrait ressembler à ceci:

Farel R

Si vous enregistrez l’image ou l’affichez seule dans votre navigateur, vous pourrez vous la présence des marges. À tout hasard, je vous livre ce calque dans deux formats, peut-être qu’il vous sera utile:

Automatisation du processus

Maintenant que nous avons un calque, on pourrait imaginer travailler par lot, sur des grandes séries d’images. Pour mes tests, j’ai récupéré toutes les images des temples de l’EREN disponible sur l’ancien site de La Vie protestante Neuchâtel.

Puis, ensuite, on travaille en ligne de commande avec ImageMagick. Souvent, quand on me voit travailler ainsi, on me prend pour un fou… Vous allez voir que la ligne de commande, ce n’est pas du snobisme, mais de l’efficacité

NB: si vous êtes allergique au code, survolez cette page jusqu’au test pratique, il y a des résultats 😉

Dimension et format

On peut supposer que les images dont nous disposons ne seront pas calibrées parfaitement. Notre but, c’est d’obtenir un carré de 300×300 pixels coupé dans le centre de l’image.

NB: n’essayez pas ces commandes pour le moment, sans savoir ce que vous faites! Vous pourriez effacer de précieuses images!

On va utiliser la commande suivante:
mogrify -resize 300x300^\> -gravity center -crop 300x300+0+0 +repage -quality 90 -sharpen 1 X.jpg

Cela vous semble compliqué, c’est normal. Cette simple ligne fait les choses suivantes:

  • elle redimensionne l’image avec le petit côté à 300 pixels (sans tenir compte du grand)
  • sans agrandir l’image (si le petit côté ne fait pas 300 pixels, le carré final ne fera pas 300×300 pixels)
  • elle découpe un carré de 300×300 pixels centré
  • elle sauve l’image et remplace l’ancienne après une petite accentuation.

Préparation pour le R

Maintenant que nous avons une image carrée et de bonne taille, nous allons nous préparer à l’application du R, avec la commande suivante:

convert X.jpg -bordercolor red -border 100x100 X-tmp.jpg

Ce que l’on fait est très simple: on ajoute une très grosse bordure rouge à l’image. Notre image de 300×300 pixels fera dont 500×500 pixels, avec une bordure rouge de 100 pixels autour.

J’ai décidé de garder cette étape, parce que le rouge se verra très bien en transparence dans le R si jamais il y avait un bug ou une image trop petite.

Application du R

Maintenant que tout est prêt, on ajoute le calque R sur l’image et on efface l’ancienne image à bord rouge:

convert X-tmp.jpg ../r.png -gravity center -composite X.jpg
rm X-tmp.jpg

Script

La force de tout cela, c’est que l’on peut automatiser les tâches en les effectuant:

  1. à la suite, pour une image donnée
  2. en boucle, pour toutes les images du répertoire

Voici donc le script final:

#!/bin/bash
 
FILES=`ls *.jpg`
for FILE in ${FILES}
do
    BASE=`basename ${FILE} .jpg`
    mogrify -resize 300x300^\> -gravity center -crop 300x300+0+0 +repage -quality 90 -sharpen 1 ${FILE}
    convert ${FILE} -bordercolor red -border 100x100 ${BASE}-tmp.jpg
    convert ${BASE}-tmp.jpg r.png -gravity center -composite ${FILE}
    rm ${BASE}-tmp.jpg
done

Vous pouvez le reprendre et l’utiliser à vos risques et périls. Dans le cas présent:

  • le script remplace tout les images du répertoire dans lequel il est utilisé
  • le script produit des images carrés (500×500 pixels) au lieu du format 500×564 pixels de la «norme FEPS»
  • si vous arrivez à lire et comprendre ce script, vous aurez compris qu’il suffit de modifier la largeur des bordures du haut et du bas pour changer ce comportement 😉

Test pratique

En reprenant les centaines images de La Vie protestante, on obtient donc ceci: Test R (page très très lourde…). Si vous souhaitez utiliser une de ces images, téléchargez-là et c’est tout: usage non commercial, dans le cadre du R de la Réforme (cf. guide), photo Laurent Borel.  Aussi disponible: un fichier zip qui contient toutes ces images.

En voici quelques-unes (je laisse volontairement les grandes marges pour mettrre les R en valeur):

saint_blaise_15 lelocle_13 landeron_3 collegiale_30 collegiale_14 boudry_8 boudry_6 boudevilliers_8 auvernier_7 auvernier_13

Résultat du test:

  • programmation du script en quelques minutes
  • transformation de 900+ photos en R en 1 ou 2 minutes
  • possibilité de sélectionner des photos en R plutôt qu’en «s’imaginant ce qu’elles pourraient devenir une fois transformées en R»

Évidemment, dans le lot de la VP, il y avait pas mal d’images assez moyennes ou inutilisables pour le R (blanc). On aurait pu faire le tri avant.

Évidemment (bis), tout cela ne remplacement jamais un R fait manuellement, avec un choix judicieux de la taille et du positionnement exacts de l’image. Mais cela donne une idée du possible.

Et ensuite

Je vous ai donné mon R transparent, utilisez-le s’il vous est utile.

Peut-être que l’utilisation de scripts en ligne de commande n’est pas votre tasse de thé. Si vous souhaitez un traitement par lot de 100 ou 1000 images, il vous suffit de me les transmettre et je vous renvoie les R en retour (offre limitée, parce que mon temps l’est aussi…). Contactez-moi avant d’essayer d’envoyer un mail de 50Mo…

Et si les scripts ne vous font pas peut, mais que vous avez un souci, n’hésitez pas à me demander une modification.

Églises, théologie et réseaux sociaux

Voici le document que j’ai présenté lors de l’atelier du 25 mars 2015 au CIDOC (Centre pour l’information et la documentation chrétiennes) à Lausanne: Présentation CIDOC (pdf).

Évidemment, ce n’est qu’un support à une présentation orale, mais il propose quelques repères qui seront peut-être utiles aux lecteurs.

Pour aller plus loin, je vous conseille notamment:

  • le site Médias sociaux de Fred Cavazza qui propose de l’actualité et des réflexions intéressantes sur l’ensemble des réseaux sociaux
  • le site  Terminaux alternatifs du même Fred Cavazza qui s’intéresse en particulier aux enjeux liés à la mobilité
  • le site etourisme.info qui montre ce qui se fait dans un domaine précis en utilisant bien Internet
  • le site PME WEB de Matthieu Corthésy qui propose un vrai travail de veille en Suisse romande
  • cette interview de Michel Serres qui remplace avantageusement la lecture de son livre Petite Poucette
  • le site aimez.ch d’Olivier Keshavjee qui recense les présences réformées romandes sur Facebook et Twitter (il suffit d’un clic pour aimer)

N’oubliez pas de suivre le CIDOC d’une manière ou d’une autre:


Ajout: Je vous signale cette série d’articles qui parlent des usages des réseaux sociaux par secteur.

Gérer les urgences sur un site web

Dans la documentation de DocBook on peut lire qu’il existe différents types de notes. Ces catégories existent aussi, un peu différentes, dans les Precautionary statements américains. Pour faire simple, il y a:

  • le danger, qui peut provoquer sans délai la mort ou des blessures sérieuses
  • le warning, qui peut provoquer la mort ou des blessures sérieuses
  • le caution, qui peut provoquer des blessures mineures ou moyennes
  • la notice, qui peut provoquer des dégâts matériels

J’aime bien cette idée d’échelle est j’essaie de l’adopter dans la maintenance des sites web. On ne parle pas de mort ou de blessures, mais il y a tout de même une idée de risque. Voici 4 niveaux d’urgence que j’applique, par ordre rapidité de réaction souhaitable:

  • immédiatement (on se connecte au CMS et on corrige): la correction de toute erreur objective qui pourrait provoquer une erreur (un action fautive):
    • un numéro de compte erroné
    • un numéro de téléphone incorrect
    • un mauvais lieu de rendez-vous (ou une mauvaise heure)
  • rapidement (si possible dans les 24h): la correction de toute erreur objective qui ne provoquera pas une erreur (pas d’action fautive):
    • une coquille orthographique
    • la fonction d’une personne qui serait inexacte
    • une liste informative incomplète
  • dès que possible (dans la semaine):  une correction qui apporte une meilleure compréhension du contenu:
    • ajout d’une information (plus de détails)
    • correction d’une formulation équivoque
    • suppression d’une information inutile
  • peut-être (sera corrigé, ou pas…): une correction qui demande une réécriture complète d’un contenu, parce que les modifications précédentes seront toujours insuffisantes. Le contenu:
    • sera corrigé lors d’une refonte plus complète du site ou
    • sera réécrit par une personne plus compétente ou
    • sera soumis à la consultation ou
    • ne sera pas corrigé parce que trop lourd par rapport aux résultats souhaités

Ce ne sont pas des règles, mais ma proposition. Je l’utilise régulièrement pour ne pas me mettre dans le rouge et avoir des critères lorsque plusieurs demandes arrivent simultanément. Lorsque l’on gère plusieurs sites, c’est nécessaire!

Et vous, avez-vous vos propres recettes d’arbitrage?

Un robot rédacteur en 15 minutes, ça vous intéresse?

Contexte

Dans son émission Sonar RTS du 26 mars 2015, Magali Philip parlait du robot rédacteur qui s’était tapé les 36000 articles en un jour. De mon point de vue technique, ce n’est rien d’autre qu’un publipostage un peu sérieux.

Pour Magali Philip, c’est une nouveauté réelle dans le contexte journalistique. Je comprends ce changement et j’essaie de montrer comment faire cela facilement. Je ne veux pas mettre des journalistes au chômage, je veux leur proposer un outil…

Les données

En premier lieu, il faut des données. En principe, un basique fichier CSV conviendra parfaitement. Je me suis rendu sur le site de la SCNF pour récupérer les statistiques des retards TGV. Il suffit de télécharger le fichier Excel, le sauver en CSV. Et nettoyer les quelques lignes qui comportent des erreurs.

Au final, ça ressemble à ceci.

En gros, la date, puis l’axe ferroviaire, puis le lieu de départ, le lieu d’arrivée, le nombre de trains prévus, le nombre de trains ayant pris le départ, le nombre de train annulés, le nombre de trains en retard et le taux de trains à l’heure.

NB: même s’il comportait certaines bizarreries, ce fichier était très propre. Ce n’est (de loin) pas toujours le cas. On dirait que beaucoup n’ont pas compris qu’un tableur n’est pas un outil de mise en page, mais un outil de gestion de données…

Puis il nous faut un schéma d’article, le template.

Template

On aimerait un resultat du genre:

PARIS LYON > VALENCE ALIXAN TGV
Le trajet de PARIS LYON vers VALENCE ALIXAN TGV sur l'axe Sud-Est prevoit 251 trains.
251 trains ont pris le depart. 19 etaient en retard.

Pour une page HTML, le template ressemblera à ceci (je ne mets pas les accents ni les balises HTML, par fainéantise):

{{ depart }} vers {{ arrive }}
Le trajet de {{ depart }} vers {{ arrive }} sur l'axe {{ axe }} prevoit {{ nombre }} trains.
{{ circule }} trains ont circule. {{ retard }} etaient en retard.

Voir le template «réel».

Lire les données et créer les articles

Ensuite, on crée un petit script en Python (ou ce que vous voulez), qui fera la chose suivante:

  • charger le fichier de données
  • charger le template
  • parcourir le fichier de données et, pour chaque ligne:
    • sélectionner les valeurs qui nous intéressent
    • effectuer d’éventuels calculs
    • envoyer ces données dans le template
    • choisir un nom unique pour la page HTML finale
    • enregistrer le tout dans le fichier nommé

Ajouter un graphique

Pour «faire joli» et attirer le chaland, on pour ajouter un graphique pour chaque page. On se rend chez Google Charts et on choisit le modèle camembert (on est en France, non?). On lit le code et on regarde où injecter les données.

La bonne nouvelle, c’est qu’on ne va pas générer les milliers de camemberts. On va simplement injecter les données dans la page web. Et quand un internaute la consultera, son navigateur va aller chez Google via l’API et dessiner le graphique.

On modifiera donc le template, avec du code Google.

Thème et variations

Pour ne pas trop ennuyer ceux qui liront toutes les fiches, on va effectuer une variation. Par exemple, au lieu de dire «X trains sont partis», on dira:

  • X trains sont partis ou
  • X trains ont pris le départ ou
  • X trains ont démarré

On va donc modifier le template avec quelque chose du genre:

{{ circule }} trains {{ go }}

Et le contenu de la variable go sera aléatoire:

synonymes = ['sont partis', 'ont pris le depart', 'ont demarre']
go = random.choice(synonymes)

On aura un template de ce genre.

Pour aller plus loin, il serait intéressant d’utiliser des conditions:

  • dans l’exemple des départementales: si les scores sont très serrés ou si un résultat est «soviétique»
  • dans l’exemple des TGV: si le taux de retard est notablement élevé, ou nul

C’est tout?

Oui, c’est tout! Dans mon exemple, j’ai généré 3500+ fiches de retard en HTML, en moins de 20 secondes, sur un vieil ordinateur sans disque SSD et avec un code quick’n dirty. Il suffit d’envoyer tous les fichiers sur le serveur et votre site statique performant et prêt à tenir la charge est prêt.

Autant dire qu’avant un rendez-vous sérieux (qui a dit les élections fédérales 2015?), il est possible de préparer un beau template, avec beaucoup de variations, une charte graphique élégante, etc.

Et ça donne quoi? Ceci: 2014-11-Sud-Est-PARIS LYON-VALENCE ALIXAN TGV

Un peu de code?

NB: Vous avez compris, j’ai intégré le template dans le code Python. Ce n’est pas très malin, mais suffisant pour un exemple. Dans le vrai monde, ce serait bien mieux de séparer les fichiers pour avoir un graphiste/développeur qui s’occupe du template en demandant les variables nécessaires. Et un programmeur qui se débrouille pour fournir les contenus dans les variables en question.

Vous avez des questions? Vous êtes journalistes et vous souhaitez tenter l’expérience en vrai? Contactez-moi, le défi m’intéresse!

Bonus

Après avoir entendu Jean-Marc Manach dans Médialogues je me dis que ce billet mérite d’être complété. Donc, voici:

  • le programme complet (exemple minimal fonctionnel) qui génère les résultats des départementales
  • le template est inclus dans le programme
  • l’utilisation de processus en parallèle pour améliorer la vitesse (multiprocessing), ce qui «cache» la boucle de l’exemple précédent

Le code:

# -*- coding: utf-8 -*-

import csv 
import jinja2
from multiprocessing import Pool

data = csv.reader(open("departementales.csv", "r"))

template = u"""
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" /> 
<title>{{ commune }}</title>

</head>
<body>
<h1>{{ commune }} - {{ canton }} - {{ departement }}</h1>
Abstention de {{ abstention }} et {{ inscrits }} inscrits.
</body>
</html>

"""

def create_page(d):
    departement = d[2]
    canton = d[4]
    commune = d[6]
    inscrits = d[7]
    abstention= d[8]

    f = open(commune+canton+departement+".html", 'w+')
    
    page = jinja2.Template(template)
    f.write(page.render(locals()))
    
    f.close()

if __name__ == '__main__':
    pool = Pool(processes=8)
    pool.map(create_page,data)


Activer OpenSearch pour votre site WordPress (ou autre)

OpenSearch est une vieille histoire que vous utilisez certainement quotidiennement dans vous en rendre compte. Et qui est malheureusement sous exploitée à mon goût.

Anatomie de Firefox

Si vous utilisez Firefox, vous avez en principe deux espaces particuliers:

  • un endroit pour entrer l’URL (c’est là que se trouve «l’adresse du site»)
  • un endroit pour effectuer des recherches

En images, cela donne:

url-recherche

La difficulté pédagogique, c’est que si ce que vous entrez dans la barre d’adresse n’est pas sous forme d’URL valide, une recherche est automatiquement lancée. Donc, en quelque sorte, la barre d’adresse devient barre de recherche avec le moteur de recherche par défaut…

Dans la barre de recherche, vous avez tout de même plus de possibilités. Dont celle de disposer de plusieurs moteurs de recherche.

OpenSearch en pratique

Si vous activez OpenSearch, vous permettez à votre site d’entrer dans la liste des moteurs de recherche de Firefox. Autrement dit, il devient possible d’effectuer une recherche sur votre site sans même s’y trouver préalablement.

Lors que vous vous trouvez sur un site qui dispose d’OpenSearch, mais qui n’est pas encore listé dans vos moteurs de recherche, vous voyez ceci (un petit + sur la loupe):

signal-opensearch

En cliquant sur la loupe, vous pouvez ajouter le moteur de recherche à votre liste:

ajouter-opensearch

Une fois la chose effectuée, vous pouvez en tout temps effectuer une recherche sur mon site, même quand vous êtes ailleurs:

recherche-externe

Évidemment, cela a très peu d’intérêt chez moi. Mais dans une base de connaissance fréquemment utilisée…

OpenSearch (code)

Pour ajouter OpenSearch à WordPress (et la majorité des CMS), vous pouvez évidemment utiliser une extension, un plugin ou autre truc du genre. Vous pouvez aussi ajouter un fichier statique et c’est réglé sans vous bouffer de ressources…

Le fichier pour mon site, c’est ici: opensearch.xml. Les seules lignes obligatoires sont:

  • le titre de votre site (ShortName)
  • sa description (Description)
  • la page qui doit être appelée pour la recherche (Url avec les attributs template et type)

Donc:

<?xml version="1.0" encoding="utf-8"?>
<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> 
  <ShortName>frdl.ch</ShortName> 
  <Description>Recherche sur le blog frdl.ch de Nicolas Friedli</Description>
  <Url type="text/html" method="get" template="http://frdl.ch/?s={searchTerms}"/>
</OpenSearchDescription>

Rédiger ce fichier doit donc prendre quelque chose comme 1 minute. Et pour que ce fichier soit détecté, on ajoute une ligne dans l’entête du site (head):

<link title="frdl.ch" type="application/opensearchdescription+xml" rel="search" href="http://frdl.ch/opensearch.xml">

Et voilà.

NB: au sens strict, une balise link peut être utilisée ailleurs que dans le head donc, par exemple, dans un widget si vous n’avez pas la possibilité de modifier les fichiers.

Et dans Chrome / Chromium?

Comme Chrome / Chromium ne sépare pas les champs d’URL et de recherche, c’est un peu différent. Une fois que votre site a été repéré par le navigateur comme disposant d’OpenSearch, il vous propose de faire une recherche ciblée:

chromium-tab

Vous utilisez votre tabulateur et la recherche est celle de votre site:

chromium-recherche

Recherche interne vs recherche Google

Attention, une recherche par OpenSearch utilise le moteur de recherche du site (avec ses forces et ses faiblesse). Elle est donc très différente d’une recherche Google sur un seul site (p.ex. site:frdl.ch qwertz). Je trouve que la présentation proposée par Chrome / Chromium peut créer la confusion.

Il n’est pas impossible de déléguer la recherche sur son site à Google. Et, par extrapolation, l’OpenSearch à Google. À vous de savoir si Google est plus ou moins performant que la recherche interne de votre site, en fonction de l’utilisation précise que vous souhaitez proposer. En gros, c’est ceci dans Url:

https://www.google.ch/search?q=site:frdl.ch+{searchTerms}

Vu la facilité de mise en œuvre de la chose, je me demande pourquoi certains sites importants n’activent pas OpenSearch…

Mon grand-père, ce casse-cou

Alors que j’effectuais quelques tests pour améliorer ma page sur les recherches Google, je me suis dit que je pourrais essayer de rechercher le nom de mon grand-père plutôt que le mien.

C’est alors que j’ai découvert, parmi d’autres choses, deux extraits de journaux d’époque.

Dans L’Impartial du 1er juillet 1965:

Malleray – Mauvaise rencontre
M. Louis Friedli, fondé de pouvoir aux usines Schäublin, a été renversé par le tracteur de manœuvres au passage à niveau près de la gare. Il souffre d’une mauvaise fracture à un bras, d’une commotion et de contusions diverses.

Et dans L’Impartial du 26 septembre 1966:

Sorvilier – Un automobiliste fatigué
M. Louis Friedli, fondé de pouvoir à Malleray, traversait Sorvilier lorsqu’il s’assoupit à son volant. Sa voiture, après avoir heurté une barrière, alla se jeter contre un mur. Le conducteur fut transporté à l’hôpital de Moutier souffrant de blessures à la cage thoracique et au visage.

Assez amusant de découvrir la manière dont on citait les victimes d’accident à l’époque, avec le nom complet et le métier.

Et preuve que ce que je propose pour recherche des informations dans Google est terriblement efficace…

Recherches Google avancées

Le moteur de recherche Google est très souvent utilisé par les internautes, parfois sans même s’en rendre compte. C’est un outil aussi efficace que méconnu. Une recherche simple donne normalement de bons résultats – Google s’y emploie pour nous rendre dépendants. Mais on peut aller beaucoup plus loin avec certaines astuces très simples.

Pour un catalogue exhaustif des recherches Google, rien ne vaut la documentation officielle ou cette documentation bien trapue. Je choisis ici de me limiter aux exemples concrets les plus utiles.

Il existe un formulaire de recherche avancée, mais je le trouve peu commode à utiliser. Et, finalement, beaucoup moins clair que la ligne de commande.

Si le sujet vous intéresse, n’hésitez pas à me contacter pour une proposition de formation.

Opérateurs logiques

AND (et)

La recherche la plus simple, c’est:
Nicolas Friedli

Ce qui signifie que Google propose des pages qui contiennent les mots Nicolas et Friedli. Je peux aussi préciser cela, en cherchant:
Nicolas+Friedli

L’opérateur est implicite. Si je ne dis rien, je recherche tous les termes demandés. Je peux aussi chercher, c’est synonyme:
Nicolas AND Friedli

OR (ou)

En changeant d’opérateur logique (qui n’est plus implicite), je peux rechercher:
Nicolas OR Friedli

Ou, dans une forme plus concise:
Nicolas|Friedli

Ces deux motifs de recherche me permettent de retrouver des pages qui contiennent ou un terme, ou l’autre terme, ou les deux. Le OR n’est pas exclusif.

– (négation)

Troisième opérateur, la négation. Je peux donc rechercher toutes les pages qui contiennent Friedli, mais pas Nicolas:
Friedli -Nicolas

C’est particulièrement utile quand une recherche est contaminée. Par exemple, DITA est un outil de documentation. Mais une recherche sur DITA proposera évidemment plein de résultats qui parlent de Dita von Teese. Je vais donc choisir:
DITA -Teese

C’est moins sexy, mais beaucoup plus efficace.

Guillemets et recherche exacte

L’utilisation de guillemets droits permet de signaler à Google que je veux trouver le motif exact. Dit autrement, les algorithmes de correction sont désactivés. Très utile si le motif de recherche est très proche d’un autre beaucoup plus connu ou si l’on souhaite retrouver une information erronée (faute d’orthographe).

Avec le motif suivant, Google corrige automatiquement (et partiellement) la recherche:
nicola friedli

Alors que
"nicola friedli"

ne permet plus, c’est logique, de me retrouver.

Attention, comme on cherche un motif exact, l’ordre des mots a évidemment son importante!

Dans la veille que j’effectue pour le projet Parpaillot, j’utilise régulièrement la recherche suivante dans Google News:
"(église|paroisse) (protestante|réformée)"

Ce qui me permet de trouver 4 expressions exactes en évitant des sujets vagues qui utilisent deux des mots dans l’article!

site: (noms de domaine)

Il est possible de limiter la recherche à un seul site web. Je me souviens avoir écrit quelque chose pour ProtestInfo, donc:
Nicolas Friedli site:protestinfo.ch

Je peux aussi exclure un nom de domaine avec l’opérateur vu précédemment. Voici une recherche intéressante:
ProtestInfo -site:protestinfo.ch

Ce qui signifie que je recherche le terme ProtestInfo partout sauf sur le site protestinfo.ch.

Il n’est pas impératif d’utiliser un domaine complet. Je peux donc chercher les occurrences de mon nom sur les sites suisses (ou plutôt les sites utilisant l’extension suisse .ch):
Nicolas Friedli site:.ch

Ou je peux travailler avec des sous-domaines. Très utile par exemple pour un blog hébergé chez wordpress.com:
site:arianebeldi.wordpress.com

À vous de décrypter ce que fait cette requête… Réponse: elle liste toutes les pages de l’excellent blog Bloggo ergo cogito et sum….. Comme ce blog est hébergé en sous-domaine (arianebeldi) de wordpress.com, limitons-nous au sous-domaine en question. Désormais, le blog en question dispose de son propre nom de domaine: www.ariane-beldi.ch.

filetype: (types de fichiers)

Une requête particulièrement utile: celle qui limite la recherche à certains types de fichiers. Par exemple:
Nicolas Friedli filetype:pdf

Encore un peu mieux, la recherche de mon nom dans les fichiers pdf hébergés sur des sites suisses:
Nicolas Friedli filetype:pdf site:.ch

Très utile pour retrouver quand on est mentionné dans des procès-verbaux et autres listes…

Exemples concrets

Soumettez-moi des exemples concrets de recherches qui vous sont utiles ou que vous n’arrivez pas à formuler correctement. J’essaierai de vous répondre ici!

Réduire le nombre résultats pour un site web avec inurl

Si j’effectue une recherche limitée à l’excellent site www.ethikos.ch, j’obtiens des milliers de résultats. La requête, vous le savez maintenant, est:
site:ethikos.ch

En observant les résultats, on voir rapidement que certaines URL sont particulières, par exemple celles qui comprennent category. Je pourrais donc essayer:
site:ethikos.ch -site:ethikos.ch/category

Cela fonctionnne, quelques centaines de pages en moins, mais c’est insuffisant. Essayons donc:
site:ethikos.ch -site:ethikos.ch/category -site:ethikos.ch/tag -site:ethikos.ch/page

Et là, je n’ai plus que les contenus, sans les taxonomies et les paginations. Comme WordPress a la mauvaise idée de dupliquer des contenus, il faut bien trouver des solutions.

On peut faire cela beaucoup plus élégamment, avec inurl, dont le nom semble explicite:
site:ethikos.ch -inurl:(category|tag|page)

Cet exemple utilise la notion de site:, la notion inurl:, la négation et le ou. Joli, non?

Détecter les hotlinks

Afin de savoir si des sites affichent des images hébergées sur votre serveur et volent votre bande passante, il suffit d’effectuer cette recherche dans Google Images:
inurl:frdl.ch -site:frdl.ch

Autrement dit: je recherche toutes les images (je suis sur Google Images) comportant mon nom de domaine dans l’URL mais qui ne se trouvent pas dans mon domaine.

Remarque: cette méthode permet aussi de détecter des liens, qui ne sont dont pas des images affichées sur le site en question. Soyez attentifs avant d’insulter le prétendu voleur.

Bien utiliser les listes Twitter

Alors que le concept de hashtag est partout, des discussion aux publicités en passant par les émissions télévisées, celui des listes reste plus difficile à appréhender. La diversité des utilisations n’en simplifie pas la compréhension.

Je signale en passant que l’on parle copieusement des listes dans les formations Twitter que je dispense.

Remarques sur ce document

Comme Twitter est remis à jour fréquemment, je ne parlerai pas ici des limites relatives aux listes, qui varient régulièrement et qui, au final, auront peu d’importance dans une grande majorité des cas. En ce qui concerne l’utilisation pratique, les guides officiels de Twitter sont bien faits et actuels: Utilisation des listes Twitter ou Créez et utilisez des listes Twitter.

Un conseil: prenez l’habitude de consulter les documentations officielles remises à jour en permanence, plutôt que des tutoriels, souvent datés, égarés sur le web. En ce qui concerne Twitter: support.twitter.com.

Remarque technique

Dans l’absolu, une liste Twitter est quelque chose de très simple. Une liste est un ensemble de comptes Twitter, appartenant à un twitto, portant un titre, privée ou publique. C’est tout!

Comme souvent avec Twitter, c’est la simplicité qui crée la difficulté. Il n’y a pas d’usage précis imposé par un concept si simple. Voici ce que je vous propose comme utilisations des listes Twitter.

Organiser sa veille

Structurer sa timeline

Une liste permet de diviser les twittos que l’on suit (= sa timeline) en plusieurs groupes distincts. D’une certaine manière, la timeline est une liste, qui même vide, existe toujours. Important: une liste permet de lister deux choses: les membres de la liste et les tweets des membres de la liste!

Lorsque le nombre de twittos suivis est trop élevé, il est possible de créer des listes pour structurer l’ensemble en petits groupes. Ce qui pose deux questions auxquelles je propose des réponses:

  • Est-ce que tout twitto suivi appartiendra forcément à une liste?
    Non, il ne sert à rien de se forcer à classer tous toute sa timeline dans des listes.
  • Est-ce qu’un twitto peut appartenir à plusieurs listes?
    Oui, mais si un twitto appartient à trop de listes, cela n’a plus vraiment d’intérêt. Et si deux listes se recoupent trop précisément, c’est peut-être qu’il ne sert à rien d’en garder deux.

Suivre sans suivre

Mais l’usage des listes permet de faire beaucoup mieux. Suivre sans suivre, cela signifie ajouter un twitto à une liste sans le suivre. En d’autre termes, le twitto n’apparaîtra pas dans la timeline, mais sera bien visible dans les tweets de la liste.

Il est parfaitement possible de suivre plusieurs milliers de twittos (via les listes) en en suivant aucun (via sa timeline). De même qu’il est parfaitement possible de suivre peu de twittos (via quelques listes) alors que sa timeline déborde!

Profiter du travail des autres

À partir du moment où les listes sont publiques, il est possible d’utiliser de manière intéressante le travail des autres.

Trouver des twittos

En regardant qui est membre d’une liste qui m’intéresse, je peux trouver des twittos qui semblent correspondre à ce que que je recherche. Je pourrai alors les ajouter soit à une de mes listes, soit à ma timeline.

S’abonner à une liste

Si je constate que presque tous les twittos d’une liste donnée m’intéressent, je peux faire beaucoup plus simple que les ajouter un à un: je peux m’abonner à la liste. L’abonnement a deux conséquences:

  • je ne suis pas maître de la gestion de la liste (je ne peux rien y changer)
  • mais je n’ai pas non plus à m’occuper de la liste (le twitto propriétaire le fait pour moi).

Note: Si une liste est bien maintenue et qu’il vous semble qu’un twitto doit y être ajouté ou en être retiré, contactez le twitto propriétaire et faites-lui cette suggestion.

Maintenir une liste

Suivre les listes des autres, c’est bien sympathique, mais c’est aussi bien de gérer les siennes. Je vois deux fonctions principales à la gestion de listes.

Mutualiser les efforts

Certains types de listes peuvent être facilement créés et gérés par un compte pour toute la communauté. C’est par exemple le cas quand les twittos qui peuvent en faire partie sont facilement listés. Exemples concrets:

  • les Conseillers nationaux qui twittent
  • les journalistes d’un média précis
  • la participants à un congrès
  • les sections locales d’un parti national

Dans ces cas là, je vous conseille la démarche suivante:

  • demander si la liste existe déjà
  • si oui, vérifiez-là et conseillez des ajouts/suppressions
  • si non, annoncez que vous la créez et demandez des la compléter
  • ensuite, maintenez la liste à jour régulièrement

C’est en maintenant votre liste à jour qu’elle prend et garde de la valeur. Rappelez son existence de temps en temps sur Twitter (et ailleurs, par exemple sur votre site web).

Valider une expertise

La taille des listes n’est pas toujours un nombre fini et les appartenances parfois difficiles à arbitrer. Pourtant, plus vos listes seront précises, mieux vous pourrez montrer votre expertise dans un milieu précis.

Il n’est pas forcément utile d’avoir des listes exhaustives: parfois c’est impossible, parfois c’est inefficace. Une bonne sélection est souvent préférable. Je préfère m’abonner en bloc au meilleur de X ou Y que d’être inondé par une timeline trop volumineuse.

Si vous maintenez correctement à jour des listes dans un ou des domaines précis, vous deviendrez rapidement un twitto de référence. On s’adressera à vous comme expert.

Officialiser ou conseiller des twittos

En maintenant un liste à jour, vous donnez une certaine caution à ses membres (sauf si vous donnez explicitement un nom qui dit le contraire à votre liste: «emmerdeurs», «à éviter», etc.).

Un média peut décider, par exemple, de maintenir à jour la liste de tous ses journalistes. Il peut officialiser leur statut. Mais il faut veiller alors à n’en oublier aucun et à supprimer les comptes qui ne doivent plus y être.

Trouver une liste

Cela fonctionne un peu comme pour trouver des twittos. Il y a plusieurs possibilités à utiliser selon ses préférences et son domaine de prédilection. On naviguera notamment parmi:

  • les listes auxquelles on a été ajouté
  • les listes maintenues par des twittos que l’on trouve intéressants
  • les listes auxquelles ces twittos intéressants ont été ajoutés

Bonne nouvelle, il est désormais possible de rechercher des listes. Dans le moteur de recherche de Twitter, il faut choisir l’option Fils.

Si vous ne trouvez rien, et avant de vous lancer dans une nouvelle liste, posez très clairement la question en postant un tweet. Vous serez probablement surpris de voir ce qui existe déjà.

Se comprendre…

Je trouve que c’est un apport secondaire, mais important, des listes. Consultez les listes auxquelles vous avez été ajouté. Vous pourrez ainsi décrypter comment on vous comprend (quel est le titre de la liste?), avec qui vous êtes associé (qui sont les autres membres de la liste?), quelle image vous donnez de vous (avez-vous des surprises dans la manière donc on vous liste?).

Regardez qui s’abonne aux listes que vous maintenez. Cela vous donne un indice quand à votre intérêt – au sens noble – pour d’autres: qui considère votre liste comme utile?

Proposer des widgets

Dernière utilité des listes: proposer une sélection de comptes qui apparaîtront dans un widget. Très utile pour afficher aussi, par exemple sur votre site personnel, d’autres comptes que le vôtre.

Dans le cas de www.reformes.ch, par exemple, une liste de sélection spéciale a été créée, proposant une vingtaine de comptes à l’affichage sur le site.


 

Merci à @magaliphilip et @EtienneGuilloud pour leurs remarques et conseils.