Skip to content

Sparql Endpoint : pourquoi j’ai du mal à exploiter des résultats d’une requête

22/01/2016

Il y a plus de 3 ans, j’écrivais en toute innocence que finalement, on pouvait utiliser les SPARQL Endpoint comme on peut utiliser les API : dans les 2 cas on structure une URL correspondant à une requête dans une base de données, et le serveur renvoie un résultat dans un format structuré.

Un cas d’école : si je veux récupérer le PPN d’un ISBN donné, j’interroge l’API Sudoc idoine en structurant une URL de ce genre : http://www.sudoc.fr/services/isbn2ppn/0195141156.

Une des grosses différences, en tant qu’utilisateur, est que le SPARQL Endpoint permet de lancer une requête que l’administrateur du site n’aura pas prévu. Alors que l’API oriente l’usage qui peut en être fait. Ainsi, je ne peux pas utiliser l’API isbn2ppn pour récupérer le nom des directeurs de thèses de ceux qui ont publié au moins un livre dont l’ISBN commencent par « 019 » et qui sont par ailleurs docteurs (oui, SPARQL permet de faire plein de requêtes complètement absurdes, comme sortir de DBpedia ou Wikidata la liste des artistes nés il y a 69 ans).

Et donc depuis plusieurs années j’utilise un tas de feuilles XSL pour enrichir mes fichiers XML de données aspirées d’API. Et je pensais pouvoir aisément faire la même chose. La seule différence serait que l’URL contiendrait une requête SPARQL, au lieu d’une requête à la syntaxe spécifique à l’API.

Mais chaque fois que je demande à un SPARQL Endpoint une sortie au format XML (donc structuré, aspirable par ma feuille XSL) plutôt qu’une sortie HTML (le paramètre dans l’URL passant de &format=text/html à &format=application/sparql-results+xml), jamais mon navigateur ne m’affiche le résultat (artistes de 69 ans via DBpedia, format XML) comme il le fait pour une API (quand on clique sur l’URL d’une requête de l’API Sudoc isbn2ppn, ça s’affiche tranquillement dans Firefox) : à chaque fois, je suis obligé d’ouvrir le fichier avec un éditeur XML, car celui-ci est proposé au téléchargement exclusivement.

J’ai cru à un bug, un problème de configuration de mon navigateur, je ne sais quoi encore.

Mais en fait non.

Si j’ai bien compris, la réponse est en bas du formulaire de ce genre de pages :

The result can only be sent back to browser, not saved on the server, see details

En gros, je ne peux pas ouvrir un fichier XML résultant d’une requête SPARQL dans mon navigateur, et c’est fait exprès. Il y a certainement une explication logique, technique, sous-jacente à ça — mais ça ne m’arrange franchement pas.

Donc je ne peux pas avoir un fichier XML en entrée contenant par exemple une liste mots-clés Rameau, et pour chacun de ces mots-clés récupérer en sortie la liste des œuvres indexées par ces mots-clés dans data.bnf.fr : simplement parce que le fichier XSL ne peut pas ouvrir le résultat de chaque requête, tant que celui-ci n’est pas hébergé dans un fichier au moins temporaire.

Alors j’ai deux solutions :

  • soit (solution actuelle) je télécharge automatiquement l’ensemble des fichiers de résultats (merci DownThemAll) pour les exploiter ensuite en local
  • soit je prends le temps de comprendre la documentation vers laquelle me renvoie Virtuoso (qui gère la base de triplets RDF), pour connecter mon explorateur de fichiers Windows en WebDAV au serveur.

Enfin bon, je suis déjà content d’avoir compris d’où venait le problème.

N.B. : les résultats au format HTML s’affichent sans difficulté dans le navigateur, sans avoir besoin d’être téléchargées. Je suppose (mais il est possible que je me plante complètement, et j’attends avec impatience les explications d’une personne vraiment compétente) que c’est parce que les navigateurs sont conçus pour fonctionner avec un cache, où ce résultat HTML va spontanément se placer sur l’ordinateur pour pouvoir être affiché.

[Traduction] Scraper Google Scholar avec R et le package rvest

18/01/2016

Ce billet est la traduction de celui-ci, , avec l’aimable autorisation de son auteur Fisseha Berhane (que je remercie, pour le billet et pour l’autorisation).
Il m’est arrivé de rajouter quelques commentaires [entre crochets].
A noter aussi le package scholar , spécialement conçu pour manipuler les données de Google Scholar.

Je vais expliquer dans ce billet comment scraper Google Scholar. Nous allons plus particulièrement utiliser le package R 'rvest' pour scraper le compte GS de mon directeur de thèse. Nous allons récupérer la liste de ses co-auteurs, combien de fois ils sont cités et leurs affiliations.

« rvest, inspiré par des librairies comme Beautiful Soup, facilite le scraping (ou le moissonnage) de données issuées de pages web HTML », indique Hadley Wickham sur le blog RStudio [RStudio est une surcouche graphique pour rendre le logiciel de stats R plus ergonomique, dans la mesure où c’est possible]. Comme rvest est conçu pour fonctionner avec magrittr, il est possible d’élaborer des opérations complexes comme des pipelines [chaînes de transformation] élégants composés de bouts de code simples et faciles à comprendre.

Packages à charger : il faut aussi récupérer ggplot2 pour générer les graphiques

library(rvest)
library(ggplot2)

Combien de fois ses articles ont-ils été cités ?

On va utiliser SelectorGadget [bookmarklet ou extension] pour déterminer quelle est la classe CSS permettant de récupérer la colonne « cited by ». [On peut aussi faire un clic droit sur une des valeurs de la colonne « Cited by », puis cliquer dans le menu contextuel sur « Examiner l’élément » et constater que les valeurs sont dans une balise <a class="gsc_a_ac"/>, toutes à l’intérieur d’un tableau ayant pour identifiant  gsc_a_b]

page <- read_html("https://scholar.google.com/citations?user=sTR9SIQAAAAJ&hl=en&oi=ao")

[Cela stocke le contenu de cette page dans la variable page.]

On spécifie le sélecteur CSS [gsc_a_ac] avec html_nodes() et on extrait le texte avec html_text(). Enfin, on convertit la chaîne de caractères pour indiquer que c’est un nombre avec as.numeric().

citations <- page %>% html_nodes ("#gsc_a_b .gsc_a_c") %>% html_text()%>%as.numeric()

La variable citations contient donc la liste des valeurs de la colonne « Cited by » :

citations 
148 96 79 64 57 57 57 55 52 50 48 37 34 33 30 28 26 25 23 22 

Créons un histogramme avec le nombre des citations :

barplot(citations, main="How many times has each paper been cited?", ylab='Number of citations', col="skyblue", xlab="")

Voici le graphique :

Co-auteurs, avec leurs affiliations et le nombre de fois où ils ont été cités

Mon directeur de thèse Ben Zaitchik est un chercheur vraiment avis. Non seulement il a toute l’habileté nécessaire pour constituer un réseau et collaborer avec d’autres chercheurs, mais il fait aussi preuve d’intelligence et de patience. Voyons donc à présent ses co-auteurs, leurs affiliations et le nombre de fois où ils ont été cités :

D’abord, comme tout à l’heure, on va utiliser SelectorGadget pour identifier le sélecteur CSS correspondant aux co-auteurs. [On trouve donc que leur nom est contenu dans un lien hypertexte <a>, à l’intérieur d’une balise <h3 class="gsc_1usr_name"> (titre de niveau 3).

  1. On stocke le contenu de la page web contenant cette liste dans une variable page
  2. On crée une variable Coauthors qui extrait de la variable page les chaînes de caractères définis grâce au sélecteur CSS
  3. On convertit cette variable en data.frame (objet qui correspond grosso modo à un tableau, dans R)]
page <- read_html("https://scholar.google.com/citations?view_op=list_colleagues&hl=fr&user=sTR9SIQAAAAJ")
Coauthors = page%>% html_nodes(css=".gsc_1usr_name a") %>% html_text()
Coauthors = as.data.frame(Coauthors)
names(Coauthors)='Coauthors'

Explorons maintenant cette liste de co-auteurs.
[La fonction head() permet de n’afficher que les premiers résultats d’une liste ou d’un data.frame. La fonction dim() donne les dimensions (ici, le nombre de lignes et le nombre de colonnes) du data.frame.]

head(Coauthors) 
                  Coauthors
1               Jason Evans
2             Mutlu Ozdogan
3            Rasmus Houborg
4          M. Tugrul Yilmaz
5 Joseph A. Santanello, Jr.
6              Seth Guikema

dim(Coauthors) 
[1] 27  1

Bref, à l’heure actuelle il a publié avec 27 autres chercheurs.

Combien de fois ses co-auteurs ont-ils été cités ?

page <- read_html("https://scholar.google.com/citations?view_op=list_colleagues&hl=en&user=sTR9SIQAAAAJ")
citations = page%>% html_nodes(css = ".gsc_1usr_cby")%>%html_text()

citations 
 [1] "Cited by 2231"  "Cited by 1273"  "Cited by 816"   "Cited by 395"   "Cited by 652"   "Cited by 1531" 
 [7] "Cited by 674"   "Cited by 467"   "Cited by 7967"  "Cited by 3968"  "Cited by 2603"  "Cited by 3468" 
[13] "Cited by 3175"  "Cited by 121"   "Cited by 32"    "Cited by 469"   "Cited by 50"    "Cited by 11"   
[19] "Cited by 1187"  "Cited by 1450"  "Cited by 12407" "Cited by 1939"  "Cited by 9"     "Cited by 706"  
[25] "Cited by 336"   "Cited by 186"   "Cited by 192" 

On ne va garder  dans citations que la valeur numérique indiquée après la chaîne de caractères « Cited by  » (en supprimant si nécessaire les signes de ponctuation, car certains nombres sont suivis du caractère *).

citations = gsub('Cited by','', citations)
citations <- gsub("[[:punct:]]", "", citations)

[vérifions le résultat]

citations
 [1] " 2231"  " 1273"  " 816"   " 395"   " 652"   " 1531"  " 674"   " 467"   " 7967"  " 3968"  " 2603"  " 3468"  " 3175" 
[14] " 121"   " 32"    " 469"   " 50"    " 11"    " 1187"  " 1450"  " 12407" " 1939"  " 9"     " 706"   " 336"   " 186"  
[27] " 192"  

Convertissons le contenu de cette variable en nombres puis en data.frame pour faciliter leur exploitation avec ggplot2

citations = as.numeric(citations)
citations = as.data.frame(citations)

Affiliation des co-auteurs

[Création d’une variable affiliation sur le même modèle que précédemment]

page <- read_html("https://scholar.google.com/citations?view_op=list_colleagues&hl=en&user=sTR9SIQAAAAJ")
affilation = page %>% html_nodes(css = ".gsc_1usr_aff")%>%html_text()
affilation = as.data.frame(affilation)
names(affilation)='Affilation'

A présent, créons un data.frame qui regroupe la liste des co-auteurs, du nombre de citations et de leurs affiliations. [cbind() va mettre côte à côte les 3 variables déjà définies plus haut : Coauthors, citations et affiliation]

cauthors=cbind(Coauthors, citations, affilation)

cauthors 
                             Coauthors citations                                                                                  Affilation
1                          Jason Evans      2231                                                               University of New South Wales
2                        Mutlu Ozdogan      1273    Assistant Professor of Environmental Science and Forest Ecology, University of Wisconsin
3                       Rasmus Houborg       816                    Research Scientist at King Abdullah University of Science and Technology
4                     M. Tugrul Yilmaz       395 Assistant Professor, Civil Engineering Department, Middle East Technical University, Turkey
5            Joseph A. Santanello, Jr.       652                                                  NASA-GSFC Hydrological Sciences Laboratory
.....

Retrions les co-auteurs sur le critère du nombre de citations

Ceci afin de produire un graphique par ordre décroissant :

cauthors$Coauthors <- factor(cauthors$Coauthors, levels = cauthors$Coauthors[order(cauthors$citations, decreasing=F)])

ggplot(cauthors,aes(Coauthors,citations))+geom_bar(stat="identity", fill="#ff8c1a",size=5)+
theme(axis.title.y   = element_blank())+ylab("# of citations")+
theme(plot.title=element_text(size = 18,colour="blue"), axis.text.y = element_text(colour="grey20",size=12))+
              ggtitle('Citations of his coauthors')+coord_flip()

Voilà le résultat

Il a publié avec des scientifiques qui ont été cités plus de 12.000 fois, et avec des étudiants comme moi qui démarrent.

En résumé

Dans ce billet, nous avons vu comment scraper Google Scholar. Nous avons scrapé la page concernant mon directeur de thèse et récupéré des données concernant les citations de ses articles et ses co-auteurs avec leurs affiliations et le nombre de fois où eux-mêmes ont été cités.

Comme nous l’avons vu dans ce billet, il est très simple de scraper le contenu d’une page HTML en utilisant le package R rvest. Il est aussi important de noter que SelectorGadget est très pratique pour identifier le sélecteur CSS qui correspond aux données qui nous intéressent.

Mise à jour : Mon directeur de thèse m’a signalé qu’il n’y a dans Google Scholar qu’une minorité de ses co-auteurs. Certains scientifiques qui ont publié avec lui et que mon directeur se serait attendu à voir être le plus cités n’apparaissent pas. En outre, les résultats pour certains de ceux qui apparaissent sont incohérents (par exemple, des seniors qui ont plus de publications, ont d’après Google Scholar moins de citations que leurs cadets). Bref, les données de Google Scholar doivent être utilisées avec précaution.

Les biens communs : dépasser le désir mimétique ? #RenéGirard

19/11/2015

L’idée de ce billet m’est venue avant les récents attentats. Je l’ai finalisé sans tenir compte de ces événements récents.

J’ai été frappé par la conjonction de 2 événements début novembre :

Le rapprochement chronologique des deux m’a semblé être l’occasion d’un rapprochement logique, en guise d’hommage à René Girard (sans prétention de ma part : juste une sorte de remerciement pour les stimulations qu’il a suscitées en moi, et ce sentiment d’intelligence, en le listant, à croire que je découvrais des trucs, alors qu’en fait pas du tout).

Désir mimétique : rappel des concepts de base

Le principe du désir mimétique, c’est qu’on oriente son désir sur certains objets, uniquement parce qu’ils sont possédés ou désirés par une autre personne, et que cette personne est une forme de modèle pour moi. Ce modèle est désigné comme médiateur.

Le fait que deux personnes désirent le même objet suscite nécessairement une rivalité, une violence qui peut prendre plusieurs formes. Dans le cadre d’une société, cette violence finit par atteindre son paroxysme et la société l’évacue en se défoulant sur un bouc émissaire qu’elle désigne alors comme cause du problème interne.

Le bouc émissaire est évacué d’une manière ou d’une autre, la société se sent mieux et ce bien-être retrouvé (temporaire) la conforte dans l’idée que le bouc émissaire était réellement responsable des tensions.

Qu’est-ce ça devient dans un contexte de biens communs, particulièrement numériques ?

En effet par définition les communs sont des biens non rivaux, il n’est donc pas possible de se les disputer (à moins qu’une personne cherche à se les approprier au détriment de toute la communauté, mais ça n’a rien à voir avec le désir mimétique).

Cet article « Faciliter la convergence par les biens communs et un environnement d’abondance » décrivant le mécanisme des communs dénonce le désir mimétique comme risque pour la communauté, mais pas tant sous l’angle de l’appropriation du commun lui-même : juste comme risque pour la cohésion de l’ensemble.

J’ai supposé au début que dans le cadre d’une communauté bénéficiant de biens communs, le désir mimétique disparaissait donc, était d’une certaine manière sublimé dans cet écosystème.

Mais c’est bien mal lire René Girard : en effet cette première hypothèse supposerait que c’est l’objet en soi qui porte une valeur le rendant désirable. Or le mécanisme du désir mimétique consiste précisément à désigner ce que l’autre possède et que je n’ai pas, comme objet du désir.

Dans le cadre des communs, l’esprit va donc chercher à identifier ce qui n’est pas partageable, pour chercher à le ravir. De quoi s’agira-t-il ?

L’article cité plus haut « Faciliter la convergence par les biens communs et un environnement d’abondance » décrit assez bien la raison pour laquelle des personnes vont activement contribuer à un projet d’enrichissement d’un bien commun (du type Wikipedia) alors qu’ils ne semblent rien y gagner : la reconnaissance de la communauté.

Un contributeur plus actif attirera davantage de reconnaissance, davantage d’attention, et c’est donc bien cette reconnaissance, cette attention, qui feront l’objet du désir mimétique (si on veut positiver, on parlera d’émulation).

Le contexte de communs n’élimine absolument pas le mécanisme du désir mimétique, il le déplace simplement sur un bien, certes immatériel, mais rival. En effet la reconnaissance, l’attention des autres consiste à monopoliser leur « temps de cerveau disponible ».

Et le bouc émissaire ?

Dans un tel environnement où le désir se focalise sur l’obtention de l’attention des autres, qui va finir par être désigné comme le bouc émissaire ?

Mon hypothèse (encore une) est la suivante : sera désigné comme bouc émissaire celui qu’on estime attirer indûment l’attention des autres, parce qu’il a des positions et des opinions discordantes au sein de la communauté (c’est cette discordance qui attire d’ailleurs l’attention).

Le troll, donc.

Ce troll sent le bouc (et réciproquement)

Autre hommage de bibliothécaire à René Girard

L’extraction de data.bnf.fr (via le Sparql Endpoint) des auteurs du XXe siècle ayant publié sur des sujets identiques à René Girard (violence, religion, sacré), etc., le tout mis sur Gephi.

Accéder à la cartographie dynamique

Et enfin les mots-clés associés à René Girard, dans les publications où il est auteur ou sujet) et les associations entre ces mots-clés

 René Girard - mots-clés Etudes sur RG

#attaqueParis : réagir ?

15/11/2015

#attaqueParis : réagir ?
Donner son sang, si on habite en région parisienne. En attendant peut-être quelques jours.

S’informer, pas n’importe comment :

  • Chercher à comprendre plus qu’à savoir
  • Ne pas suivre les liens intitulés « Revivez les événements… » : ils sont racoleurs, mais ils sont surtout insultants
  • Fuir le temps réel et préférer le temps long, chercher des sources qui s’efforcent de replacer les événements en perspectives : livres, articles de fond, interviews d’universitaires ou de journalistes spécialistes du Moyen Orient
    Préférer France Culture à BFMTV.
  • Contrôler les sources des infos qu’on va voir circuler. Les rumeurs seront multiples (le soir même des attentats, il était question d’un immense incendie à Calais).
  • Si on ne veut/peut pas quitter Twitter, avoir conscience que ce n’y sont que des sentiments (c’est important aussi), pas des avis éclairés.
  • Ne pas écouter les personnalités politiques : leur analyse n’aura généralement aucune valeur, et leurs propositions suivent d’autres objectifs.
  • S’attendre à voir arriver des complotistes. Anticiper.
  • Dans le doute, éviter les convictions évidentes (conflit israëlo-palestinien, etc.). Prendre conscience que la source du problème n’est pas dans nos quartiers, même difficiles ; elle est à quelques milliers de kilomètres.
  • Ne pas croire aux solutions faciles (par exemple : enfermer toutes les personnes suspectes de terrorisme ; envahir l’Irak et la Syrie pour détruire Daesh ; ou au contraire croire qu’en cessant toute intervention ils nous laisseront tranquilles).

Nous allons espérer trouver un sens à ce qui s’est passé. Or il est tout à fait possible de le trouver : oui, il est possible de trouver les explications aux actes des terroristes, il est possible de comprendre leurs motivations, les raisons pour lesquelles ils ont fait tout ça. C’est très important : le comprendre nous permettra d’éviter d’aller droit dans la direction qu’ils veulent nous faire prendre (au hasard : plus de sécuritaire, une méfiance institutionnalisée à l’égard des réfugiés et des musulmans).

Mais si nous pouvons trouver un sens aux actes meurtriers des terroristes, il faut renoncer à trouver un sens aux morts elles-mêmes. Même si c’est évidemment ce dont nous aurions besoin.

La BU Drive : un concept à creuser

12/11/2015

Résumé : substituer aux traditionnelles réservations en bibliothèque un service de « Drive » à l’image de ce que proposent plusieurs grandes surfaces. Ce qui au départ pourrait n’être qu’une opération marketing correspond en réalité à un service conceptuellement très différent, beaucoup plus adapté à l’environnement informationnel contemporain : la réservation est adaptée au monde de l’information rare ; le service de Drive est faite pour notre monde de l’information abondante.

Contexte

Les réservations en ligne

Tout est parti d’un problème technique : Cela fait plus d’un an que nous proposons aux lecteurs du réseau des BU un service « Faire venir un livre ». Mais pour cela ils sont obligés de passer en banque de prêt pour bénéficier de ce service.

En effet dans Aleph/Primo, la possibilité de « faire venir un livre » d’une BU à une autre est une réservation, dont on modifie le paramètre « Bibliothèque de retrait ». Il n’était donc pas envisageable de permettre aux lecteurs de réserver un ouvrage qui était en rayon : on ne réserve pas un ouvrage en rayon, ça n’a pas de sens.

Du coup, pour assurer le service « Faire venir un livre », la consigne pour les collègues en banque de prêt était d’outrepasser la configuration (qui empêchait la réservation de livres disponibles).

Puis nous nous sommes dit que c’était quand même absurde, en 2015, qu’un service de ce genre ne puisse pas se faire en ligne.

Donc à la rentrée de septembre nous avons activé la possibilité de faire des réservations d’ouvrages disponibles : l’hypothèse de départ était que les lecteurs n’avaient pas de raison de réserver un livre disponible, si c’était pour le retirer dans la bibliothèque où il se trouvait déjà. Autant aller le chercher sans perdre de temps à le « réserver ». Nous avions supposé que les cas seraient peu nombreux, et que pour les quelques-uns qui se produiraient… on ferait au mieux.

Résultat

De nombreux étudiants se sont mis à faire des réservations « sur place » d’ouvrages en rayon. Jusqu’à 30 par jour dans une des bibliothèques.

C’était un succès inattendu (« ça alors, les étudiants utilisent leur compte lecteur ! »), mais qui a rapidement posé des problèmes d’organisation et de charge de travail : la fréquence pour aller chercher les ouvrages en rayon, la tentation de dire aux lecteurs d’y aller eux-mêmes – et que dire aux lecteurs qui se présentent entre temps à l’accueil, le livre en main, pour l’emprunter alors qu’il vient d’être réservé par quelqu’un d’autre.

Ce qui frappe, c’est que le service n’était pas compris. Un étudiant se connecte à l’opac dans une BU, réserve un ouvrage et vient ensuite en banque de prêt : « Je l’ai réservé… et maintenant comment je fais pour l’obtenir ? ».

Une collègue explique qu’une sorte de travail à la chaîne se met en place à certaines heures de la journée : les lecteurs défilent pour venir chercher leur livre réservé…

Bref, sans le savoir, nous avons d’emblée mis en place un nouveau service (quand bien même ce nouveau service s’appellerait encore « réservation »). Et nous n’étions pas en mesure de l’assurer correctement, nous n’étions même pas sûrs de savoir si nous voulions l’assurer : d’une certaine manière, ces lecteurs prenaient à rebrousse-poil toute l’évolution des bibliothèques depuis des décennies, consistant à faire disparaître les magasins et à tout mettre en libre accès.

Surprise : ces lecteurs préféraient passer par l’opac pour obtenir qu’on leur fournisse le livre, alors que nous avions tout fait pour qu’ils puissent y accéder directement !

Une collègue de la BU d’Angers (merci à elle !) nous a permis de trouver comment permettre aux lecteurs de réserver des ouvrages en rayon, à condition que la bibliothèque de retrait soit différente de leur bibliothèque de « stockage ». Donc nous sommes restés pour l’instant sur une distinction des deux services : réservation / faire venir un livre. Tout en voulant réfléchir à cette expérience inattendue.

Le Drive, qu’est-ce que ça change ?

Concept marketing

Ce n’est pas anodin, mais en termes de communication, le Drive serait beaucoup plus simple à afficher. C’est en effet un concept bien plus maîtrisé par nos lecteurs, parce qu’existant dans d’autres environnements que les bibliothèques.

Évidemment, ça permet donc de dépoussiérer un vieux service, en l’associant à un service plus moderne, et bien apprécié de pas mal de monde. Et puis un mot anglais, pour valoriser un service, ça passe souvent mieux…

Pour les limites du service aussi, ça permet de faire plus aisément comprendre pourquoi on ne va pas garder le livre indéfiniment hors des rayons à leur disposition ; voire pourquoi nous pourrions suspendre le service pour certains lecteurs qui trop souvent ne viendraient pas chercher les ouvrages réservés : dans une grande surface aussi, on ne laisse pas trois jours un panier pour un client.

Philosophie sous-jacente

Si le Drive remplace les réservations, ça n’enlève rien à ce qui était offert par l’ancien service (on met de côté une ressource pour vous), et ça rajoute une dimension fondamentale :

Quand, à titre personnel, je vais choisir de récupérer des courses en Drive plutôt que de passer moi-même dans les rayons avec mon caddy, ce n’est pas un problème de compétence : je suis capable de trouver les produits que j’ai l’habitude d’acheter chaque semaine. Souvent même, le site web du supermarché va m’embarrasser davantage que ses rayonnages.

Le problème auquel le Drive vient apporter une solution, c’est la question du temps disponible, ou encore la question du délai entre le besoin et sa satisfaction.

Or ces deux questions ont tout à voir avec l’évolution de l’économie informationnelle depuis 20 ans.

Le temps disponible

Si nos lecteurs ont tant apprécié ce service, c’est parce qu’il leur faisait gagner du temps.

Au lieu de passer 2, 5 ou 10 minutes dans la bibliothèque, ils peuvent activer une réservation alors qu’ils sont dans le bus, passer en coup de vent à la bibliothèque et filer en cours aussitôt.

Je ne vous ferai pas le couplet déjà mille fois lu sur notre société du temps réel, du manque de temps, etc. Toujours est-il que dans cet univers-là, la bibliothèque offrant un service de Drive serait complètement en phase avec la société qu’elle dessert.

Économie de l’attention, économie de la rareté, économie de l’abondance

Les réservations sont nées dans un contexte de rareté de l’information : pour votre travail universitaire, vous devez absolument accéder à certaines informations. Or elles sont dans un livre. Celui-ci a été emprunté par quelqu’un d’autre, donc vous le réserver.

Vous êtes alors prêt à attendre trois semaines pour accéder à cette information.

Aujourd’hui, trois semaines sont trop longues. Elles sont interminables. Elles sont même inimaginables. Soit le livre est disponible et j’accède à l’information tout de suite, soit je trouve la ressource autrement (en ligne, légalement ou non), soit j’ai de toute façon tant d’autres informations à lire (économie de l’attention) que je peux aussi bien me passer de celles-là.

Les seules informations qui valent la peine d’être lues, sont celles dont on peut prendre connaissance sans effort. La lecture du document peut être un effort ; l’accès à ce document ne peut pas en être un (si c’en est un, je renonce simplement à y accéder).

Évidemment, je vous retrace tout ça à la louche : il y a des cas où le lecteur sera prêt à attendre quelques jours ou quelques semaines pour obtenir l’ouvrage réservé. Mais cette proportion de lecteurs, ou plutôt le nombre de fois où un lecteur sera confronté à une telle situation ne va faire que décroître.

La réservation était légitime et utile dans ce contexte de ressource rare. Dans notre économie de l’information abondante, elle perd beaucoup d’intérêt.

En revanche le Drive y gagne toute sa légitimité. Il est bien plus utile pour les livres disponibles (le service consiste alors à aller chercher le livre pour le lecteur, et à le mettre à sa disposition dans la bibliothèque de son choix) que pour les livres empruntés (on retombe alors dans la réservation classique).

Une autre leçon…

De la petite période (deux ou trois semaines) durant laquelle ce service a été involontairement mis en place à Nice, je garde une grande surprise :

  • Certains lecteurs préfèrent (inconsciemment) passer par l’opac plutôt qu’aller dans les rayons pour sélectionner l’ouvrage qu’ils veulent
  • Ces mêmes lecteurs, plus nombreux qu’on ne l’aurait cru, ont la démarche de s’authentifier sur le site de la bibliothèque pour accéder aux services qu’elle lui propose.

Ces deux éléments m’incitent à considérer un peu différemment l’opac, dont je pensais qu’il ne pouvait servir qu’en ultime recours, une fois que le lecteur aura échoué à trouver son bonheur dans les rayons. Cela ne signifie pas que cette population-là n’existe pas, mais que l’autre, celle qui navigue par préférence sur l’opac, est plus importante que je ne le croyais.

Qu’attend-on ?

(par « on », je parle des bibliothèques en général, pas du SCD de Nice en particulier où je ne suis pas missionné pour instruire cette question)

On attend d’abord de savoir si c’est bien ce qu’on veut : le temps à y consacrer est-il légitime, au regard de ce qu’on pourrait en faire d’autre ? Et que fait-on du souhait que les lecteurs maîtrisent l’espace « bibliothèque », la circulation dans les collections, la compréhension de la signalétique, la diversité et la cohérence des collections, etc.

On attend ensuite d’évaluer l’organisation que ça implique :

  • Pour honorer les demandes :
    charge de travail (manutention), fréquence de retrait des ouvrages des rayons (une fois par jour ? plusieurs fois ?), largeur des rayonnages au niveau de la banque de prêt pour les demandes (difficile en amont d’évaluer la volumétrie), éléments de langage pour communiquer là-dessus
  • Pour ne pas les honorer :
    que faire quand un autre lecteur vient emprunter le livre (réservé par un autre) avant qu’on ait eu le temps de le retirer des rayons ? que faire des livres non retirés par leurs « réservateurs » ? Que faire des lecteurs qui systématiquement réservent à tout hasard, et ne viennent chercher leurs livres qu’une fois sur dix ?

Enfin, je trouve qu’il y aurait une réflexion très intéressante à mener sur la manière dont ce genre de service pourrait s’articuler avec des automates de prêt (sans forcément faire l’acquisition de casiers de réservation)

Et vous ?

Est-ce que certains SCD ont déjà mis ça en place ? Je ne parle pas de la possibilité technique de réserver des livres disponibles, je parle de la valorisation d’un service consistant à aller chercher le livre en rayon à la place du lecteur, pour lui faciliter la vie et lui économiser du temps ?

Automatisation Colodus/JavaScript : limites, problèmes et prospectives

08/10/2015

Tous les billets de la série « Automatisation Colodus avec JavaScript »

Problèmes

Nombre de caractères dans l’URL d’un favori sous Firefox : il n’est pas possible de charger toute une bibliothèque via un favori Firefox, même en le laissant tourner  plusieurs jours : le nombre de caractères dans un favori est limité à 65536 caractères. Et quand on y stocke des données d’exemplaires, ça peut aller assez vite

Ralentissements quand un script contient trop d’exemplaires : c’est plus problématique. Au fur et à mesure que les exemplaires défilent, la vitesse d’exécution ralentit (je suppose que c’est dû à une mémoire cache qui s’alourdit peu à peu, ou quelque chose comme ça). Plus le script contient d’exemplaires, plus le temps moyen passé par exemplaire s’allonge (même si en début de script les premiers exemplaires traités sont toujours très rapides).

Nb d’exemplaires à traiter temps (secondes) Temps (secondes) / exemplaire
10 34 3,4
20 105 5,25
30 180 6
40 325 8,125
50 495 9,9

bookmarklet colodus - temps par exemplaire

Zone L035 : la création de données locales génère des pop-ups d’erreurs. Pourtant quand on les ferme ou qu’on les bloque, ça n’empêche manifestement pas la création correcte de la zone locale.

J’ai mis du temps à comprendre d’où vient le problème : les pop-up apparaissent à partir de la 2e création de zone L035 (dans le 2e PPN, donc). Et à chaque nouvelle zone se rajoute une pop-up supplémentaire (lors du 4e PPN, il y aura 3 pop-up).
S’il faut les fermer à la main, ça devient vite désespérant. La solution que nous avons trouvée pour l’instant est d’installer sur les postes qui font tourner ces script une extension Firefox qui bloque très strictement les pop-up de Colodus lors du lancement du script.
Voici comment j’ai cru comprendre la raison du problème : lorsque le script donne pour consigne d’enregistrer la zone de données locales (cliquer sur le bouton « enregistrer les données locales ») il n’imite pas exactement l’action d’un internaute cliquant sur « Enregistrer ». Du coup le code de la page HTML est modifié est garde en mémoire la consigne de créer une zone L035. Lors de la création de la L035 suivante, le code précédent est toujours dans la page, et la validation de la 2e zone envoie au serveur Colodus l’ordre simultané de créer 2 L035… Mais bon, ça n’empêche pas de créer pour autant la bonne zone, alors en attendant mieux on se contente de bloquer l’affichage de la pop-up. Ce n’est pas satisfaisant, mais ça fonctionne..

Pistes d’amélioration

Authentification : nous avions envisagé que l’exécution des scripts soit centralisée (une personne se chargeant de les faire passer pour l’ensemble des RCR). Mais je craignais un peu la confusion dans l’utilisation successive de logins propres à chaque RCR. Du coup le login est mis dans le script, ce qui n’est pas forcément sécurisé. Je suppose qu’il est possible de déporter la gestion des mots de passe sur un serveur, mais je ne sais pas faire !

Contrôles bibliographiques : les rapports Aleph qui génère le code JavaScript contiennent aussi la liste des notices concernées, et pour chaque notice ils effectuent un certain nombre de contrôle qualité sur les notices Sudoc. Du coup nous avons dû réécrire ce qui a déjà été fait par ailleurs pour l’application CheckSudoc. L’idéal serait donc qu’une API soit développée pour CheckSudoc, afin qu’on puisse s’en servir non seulement comme interface web, mais aussi par le biais d’applications de type SIGB, afin de pouvoir exploiter ses contrôles depuis une application de ce genre (et tant qu’à faire avec des options sur le niveau d’exigence que l’on souhaite mettre en place…).

Mutualisation du code : si l’interface Colodus évolue, le code JavaScript qui agit sur ces pages devra évoluer aussi. Donc si une telle solution technique est déployée pour plusieurs types de situations (acquisitions, pilon, recotation) et dans plusieurs établissements, ça veut dire autant de mises à jour à reporter systématiquement. L’idéal serait donc de gérer les fonctions elles-mêmes de manière centralisée, et que le script les invoque au moment de les exécuter, sans qu’il soit nécessaire de les reproduire à l’identique dans chaque bookmarklet (l’appel de l’URL du fichier qui les contient suffirait alors).
Un tel fichier permettrait de mutualiser aisément la mise à jour des fonctions.
Et j’en profite pour glisser que l’idéal serait qu’à terme il ait une URL en http://*.abes.fr, car c’est l’Abes qui est la plus à même de voir arriver des évolutions dans le code des pages de Colodus. Ces fonctions JavaScript pourraient même être nativement intégrées à l’interface (il y a déjà un nombre considérable de fonctions JavaScript qui font tourner Colodus !)

Fonctions avec des paramètres vides : notamment pour la fonction FormExemplaire() qui alimente le formulaire de création d’exemplaire sous Colodus. Le SCD de Nice indique systématiquement, pour chaque exemplaire, 6 informations : Bibliothèque, localisation, cote, n° d’inventaire, code-barres et règle de PEB. De nombreuses bibliothèques ne mettent dans le Sudoc que la mention de site, ou site + localisation, ou site + localisation + cote (+ PEB à chaque fois, bien sûr). La fonction devrait tenir compte de l’hpothèse que certains paramètres attendus (CB et n° d’inventaire notamment) soient vides, et ne générer ces champs dans Colodus que si nécessaire.

Adoptez un script !

2 scripts pour le prix d’un. Kitten – photo Viola’s Visions — CC-BY-NC-SA-2.0

Si j’ai mis en ligne tous ces billets, ce n’est pas pour vous dire : regardez comme on est trop forts. L’objectif, c’est évidemment que d’autres établissements puissent s’emparer de cette possibilité, sans y passer tout le temps que j’y ai moi-même consacré, pour l’adapter à leur situation propre (circuits, intervenants, type de données concernées, etc.).

C’est clair qu’il manque un mode d’emploi simple, un how to pour implémenter tout ça chez soi.

Je veux bien bosser avec les établissements intéressés pour les accompagner dans cette mise en oeuvre, à condition qu’ils contribuent à documenter (relativement à leur situation propre et à leur SIGB) la manière dont d’autres bibliothèques pourraient faire comme eux. Les premières expériences d’appropriation du code permettrait justement de rédiger un tel mode d’emploi.

JavaScript/Colodus : et pour quelques lignes de code de plus

06/10/2015

Dans les billets précédents, je vous ai décrit les principes, l’organisation interne (workflows) et la logique du code (en-tête avec déclaration des fonctions + quelques exemples).

Voici des codes complets « pour de vrai » (sauf les logins d’authentification) à chaque fois pour 3 PPN traités. Vous verrez qu’il y a des bouts de code en plus que je n’ai pas détaillés précédemment. Je ne sais pas si ça sert à quelque chose que je les précise encore : le jour où ça vous intéresse, je suppose que soit vous vous plongerez dedans, soit vous viendrez poser la question en commentaire. D’ici là…

J’ai rajouté des sauts de ligne pour plus de lisibilité, mais de toute façon ils ne sont pas gênants dans le code : quand on copie-colle le code tel quel dans un favori, ils sont interprétés comme des espaces et ça va très bien.

Les 3 exemples sont aussi récupérables dans un fichier déposé sur Github. Ce sera peut-être plus lisible là-bas…

Acquisitions courantes

(Le script crée un exemplaire sous chaque PPN)

javascript:/*ColSJA-06/10/15*/function auth()
{jQuery('#login').val("050CX52");jQuery('#pass').val("colNABC");jQuery('#boutonlog').click();};function SearchPPN(ppn) {var ppn;jQuery(%22input[id*='ppn']%22).val(ppn);document.getElementById('boutonsearch').click();};function CreerEx() {document.getElementById('boutoncrexpl').click();};function FormExemplaire(inv,barcode,BU,loc,cote,PEB) {var inv;var barcode;var BU;var loc;var cote;var PEB;document.getElementById('boutoncrexpl').click();divparent=window.document.getElementById('E9xx');divparent3XX=window.document.getElementById('E3xx');div930=divparent.getElementsByClassName('E930_Div');divid930=div930[0].getAttribute('id');ajLt('record0','E915',null,null,null,null,null,null,null);div915=divparent.getElementsByClassName('E915_Div');divid915=div915[0].getAttribute('id');jQuery(%22input[id*='E915_a']%22).val(inv);ajt('record0','E915_b',null,divid915,null,null,null,null,null);jQuery(%22input[id*='E915_b']%22).val(barcode);ajt('record0','E930_c',null,divid930,null,null,null,null,null);jQuery(%22input[id*='E930_c']%22).val(BU);ajt('record0','E930_d',null,divid930,null,null,null,null,null);jQuery(%22input[id*='E930_d']%22).val(loc);jQuery(%22input[id*='E930_a']%22).val(cote);jQuery(%22select[id*='E930_j']%22).val(PEB);jQuery('#boutonsave').click();};function L035(NoAlp){var NoAlp;var champAlp = 'L035%20##$aALP' +  NoAlp;document.getElementById('boutonCreloc').click();document.getElementsByTagName('textarea')[0].value=champAlp;};function EnregistrerDonneesLoc(){jQuery('button:contains(%22Enregistrer%22)').click();};function Annuler() {jQuery('button:contains(%22Annuler%22)').click();}
if (/colodus.sudoc.fr/.test(window.location.href))
{
if (jQuery('div#messConnect').text().length != 0) {location.reload();}
else {
auth();
SearchPPN("185829538"); if (!jQuery('#listeExpl table tbody tr')[0]) FormExemplaire("2015-SJA-580","0962091260","SJA","ECO","333.7 MER","u");
SearchPPN("185668046"); if (!jQuery('#listeExpl table tbody tr')[0]) FormExemplaire("2015-SJA-545","0962091192","SJA","ECO","334.906 4 MAI","u");
SearchPPN("183909941"); if (!jQuery('#listeExpl table tbody tr')[0]) FormExemplaire("2015-SJA-546","0962091215","SJA","ECO","338.88 BAS","u");
SearchPPN("185829538"); if (document.getElementById('boutonCreloc')) {L035("000359094");EnregistrerDonneesLoc();}
SearchPPN("185668046"); if (document.getElementById('boutonCreloc')) {L035("000359112");EnregistrerDonneesLoc();}
SearchPPN("183909941"); if (document.getElementById('boutonCreloc')) {L035("000359143");EnregistrerDonneesLoc();};
Annuler();
}
}
else {window.location.href = 'http://colodus.sudoc.fr';}

Pilon/désherbage

(le script supprime tous les exemplaires existants pour le RCR concerné, et si c’est pertinent il en recrée un)

javascript:/*ColBU Sciences-06/10/15*/function auth(){jQuery('#login').val("050CX41");jQuery('#pass').val("colBAC114");jQuery('#boutonlog').click();};function SearchPPN(ppn) {var ppn;jQuery(%22input[id*='ppn']%22).val(ppn);document.getElementById('boutonsearch').click();};function CreerEx() {document.getElementById('boutoncrexpl').click();};function FormExemplaire(inv,barcode,BU,loc,cote,PEB) {var inv;var barcode;var BU;var loc;var cote;var PEB;document.getElementById('boutoncrexpl').click();divparent=window.document.getElementById('E9xx');divparent3XX=window.document.getElementById('E3xx');div930=divparent.getElementsByClassName('E930_Div');divid930=div930[0].getAttribute('id');ajLt('record0','E915',null,null,null,null,null,null,null);div915=divparent.getElementsByClassName('E915_Div');divid915=div915[0].getAttribute('id');jQuery(%22input[id*='E915_a']%22).val(inv);ajt('record0','E915_b',null,divid915,null,null,null,null,null);jQuery(%22input[id*='E915_b']%22).val(barcode);ajt('record0','E930_c',null,divid930,null,null,null,null,null);jQuery(%22input[id*='E930_c']%22).val(BU);ajt('record0','E930_d',null,divid930,null,null,null,null,null);jQuery(%22input[id*='E930_d']%22).val(loc);jQuery(%22input[id*='E930_a']%22).val(cote);jQuery(%22select[id*='E930_j']%22).val(PEB);jQuery('#boutonsave').click();};function SupprimerEx(){ var Ex = jQuery('#TabListeExpl tbody tr'); var NbEx = Ex.length; var i = 0; while (i < NbEx) { jQuery('#supexpl').click(); jQuery('button:contains(%22Supprimer%22)')[0].click(); i++; }}
if (/colodus.sudoc.fr/.test(window.location.href))
{
if (jQuery('div#messConnect').text().length != 0) {location.reload();}
else
{
auth();
SearchPPN("135419255");SupprimerEx();
SearchPPN("012495883");SupprimerEx();
SearchPPN("087392135");SupprimerEx(); FormExemplaire("25163-01-A","0092032829","SCIEN","MAN","628.168 ATT","u");
SearchPPN("052887391");SupprimerEx();
SearchPPN("056522843");SupprimerEx(); FormExemplaire("21285-33-A","0092021691","SCIEN","BUR1","023 MUL","g");
}
}
else {window.location.href = 'http://colodus.sudoc.fr';}

Recotation/Relocalition

(le script identifie chaque exemplaire par son code-barres présent dans le Sudoc, modifie les zones de cote et de localisation, et enregistre les modifications)

Il est censé utiliser une fonction EditerExParCB pour retrouver le bon exemplaire dans le tableau des exemplaires Colodus, mais comme ça marche une fois sur 2, finalement je réécris systématiquement l’ensemble des consignes pour chaque exemplaire…

javascript:/*ColLASH-06/10/15*/function auth(){jQuery('#login').val("050CX52");jQuery('#pass').val("colNABC");jQuery('#boutonlog').click();};function SearchPPN(ppn) {var ppn;jQuery(%22input[id*='ppn']%22).val(ppn);document.getElementById('boutonsearch').click();};function Recotation(cote,codeLocalisation){jQuery(%22input[id*='E930_a']%22).val(cote);jQuery(%22input[id*='E930_d']%22).val(codeLocalisation);jQuery('#boutonsave').click();};function EditerExParCB(CB){jQuery('tr:contains(CB) td a.option_editer').click();}
if (/colodus.sudoc.fr/.test(window.location.href))
{
if (jQuery('div#messConnect').text().length != 0) {location.reload();}
else
{
auth();
SearchPPN("172702798"); function edit1(){jQuery('tr:contains(%22$b0922154010%22) td a.option_editer').click();}edit1(); Recotation(%22411 SZE%22,%22SL2%22);
SearchPPN("082313172"); function edit2(){jQuery('tr:contains(%22$b0922091925%22) td a.option_editer').click();}edit2(); Recotation(%22443.1 RHE%22,%22SL2%22);
SearchPPN("007639929"); function edit3(){jQuery('tr:contains(%22$b0922067436%22) td a.option_editer').click();}edit3(); Recotation(%22447.01 AND%22,%22SL2%22);
}
}
else {window.location.href = 'http://colodus.sudoc.fr';}

Suivre

Recevez les nouvelles publications par mail.

Rejoignez 138 autres abonnés