Utiliser les API de Google est de plus en plus fréquent, mais une question reste toujours en suspens : quel langage utiliser pour quelle API ? Nous allons étudier le cas de l'API Knowledge Graph car elle est simple à prendre en main, et faire un focus sur les différences d'usage entre trois langages connus du moment : le classique PHP, l'indispensable Javascript et le retour en grâce de Python.

Par Mathieu Chartier

Nous avons déjà traité de nombreuses API au sein des lettres d'Abondance mais on se posait à chaque fois la question du choix du langage à utiliser. Dans les faits, aucun n'est parfait, et nul n'est mauvais. Il s'agit d'utiliser le bon langage au bon moment, et pour la bonne application. Notre choix s'est porté dans cet article sur Python, PHP et Javascript car ce sont des langages dans la tendance, toujours très appréciés par les développeurs. Nous nous sommes référés aux classements PYPL (source : http://pypl.github.io/PYPL.html) et Tiobe (source : https://www.tiobe.com/tiobe-index) pour faire ce choix, mais d'autres langages auraient pu être ajoutés dans la balance. Alors voyons les bénéfices ou défauts de chaque mouture…

Quel langage pour quel usage ?

Avant de se lancer à corps perdu dans un projet de développement, il convient de bien réfléchir aux langages à utiliser. Dans le Web, il est tendance d'utiliser Javascript à tout-va par exemple, alors que quelques années auparavant, cela était presque banni tant les navigateurs pouvaient générer des incompatibilités avec ce langage. PHP, qui reste à ce jour le langage le plus utilisé au monde dans le Web (plus de 80% de parts de marché selon W3Techs), est au contraire souvent rabaissé, bien que depuis PHP 7.0, ce langage ait pris une tournure intéressante. Python connait lui un regain d'intérêt majeur depuis l'émergence de l'intelligence artificielle et surtout de la mise en avant de Google (notamment avec la librairie Tensor Flow). Il est pourtant le plus ancien langage, sorti dès 1991, mais ce ne sont pas les quelques sites web réalisés avec le CMS Django qui l'ont mis sur le devant de la scène.


Alors, pourquoi tant de vagues au sein des langages nous direz-vous ? Nous pourrions penser qu'il s'agit uniquement de choix basés sur les qualités intrinsèques de chacun mais en réalité, il reste encore une part de « tendance » à suivre. Alors, voyons quelques atouts de chacun pour ne pas céder à la mode, mais plutôt à des choix réfléchis :

  • PHP est le langage le plus utilisé dans le Web, car il a été créé pour cet usage. Depuis PHP 7, sa rapidité ne peut guère être remise en cause et la facilité d'accès du langage en font une alternative fort intéressante. En revanche, pour utiliser les API de Google, il faudra passer soit par un programme fait maison, soit par la bibliothèque Google PHP API Client, ce qui ne facilite pas la tâche, tant la documentation n'est pas remise à jour régulièrement.
  • Javascript est en pleine forme depuis les dernières versions d'Ecmascript (EcmaScript 6 actuellement est la version intéressante, mais les prochaines offrent de belles promesses). Le langage a l'avantage de baigner dans l'usage côté client et côté serveur (si besoin), mais aussi de profiter des événements utilisateurs. Ainsi, un survol à la souris ou un clic au stylet peut entraîner une action, ce qui est bien pratique à l'heure où UX et ergonomie redeviennent des priorités. Son seul inconvénient est d'être vraiment un langage à part en termes de développement, on parle ici d'un langage orienté objet à prototype. Il peut donc s'avérer complexe à maîtriser pour les plus débutants.
  • Python est le langage idéal pour débuter dans la programmation tant il n'est pas verbeux. En effet, il offre une syntaxe légère (voire transparente dans bien des cas) mais profite de milliers de modules conçus pour proposer de nouvelles fonctionnalités. En d'autres termes, il offre un large panel de possibilités tout en permettant d'écrire du code de manière condensée. Nous verrons par la suite que le code le plus court sera celui proposé en Python, comme souvent. Son défaut en revanche est de ne pas être lié au Web à proprement parler, nous ne pourrons donc pas intégrer facilement un applicatif sur les API de Google dans un site, mais plutôt pour créer un logiciel ou un programme d'analyse, etc.

Comment fonctionne l'API Knowledge Graph ?

Comme nous l'évoquions en préambule, l'API Knowledge Graph est un exemple parfait pour étudier les forces et faiblesses des trois langages que nous avons choisi d'utiliser. Vous pouvez la tester au sein de l'APIs Explorer de Google ou passer directement par la console https://console.cloud.google.com/apis/ pour l'activer dans un de vos projets. Il ne faudra qu'une clé d'API pour l'utiliser, ce qui représente le plus simple usage à ce jour.

Officialisée en décembre 2015, L'API permet de rechercher des entités (en lecture seule) au sein du Knowledge Graph. Ainsi, nous pouvons retrouver des informations sur tout sujet traité dans le graphe de connaissance de Google, comme dans la capture de la figure 1 avec une recherche sur « Paris ».


Fig.1. Test de l'API Knowledge Graph avec l'APIs Explorer de Google.

La documentation officielle de l'API donne accès à toutes les informations de l'unique méthode proposée : entities.search.

Avec cette fonctionnalité, Google indique qu'il est possible de réaliser plusieurs actions :

  • Obtenir une liste de classement des entités les plus notables selon certains critères ;
  • Compléter les entités prédictives dans une recherche ;
  • Annoter ou organiser les contenus selon les entités du Knowledge Graph.

L'API retourne un résultat en JSON-LD compatible avec le protocole Schema.org. Ainsi, il est possible de récupérer des données au bon format directement pour l'utiliser dans un site web ou une application si nécessaire. Tout l'intérêt de l'API étant bien entendu de pouvoir nourrir les entités déjà connues ou de les utiliser à bon escient en vérifiant leur existence, leur classement, etc.

La méthode entities.search propose plusieurs paramètres optionnels qui sont détaillés dans la documentation. Voici la liste complète des paramètres utilisables :

  • key attend obligatoirement la clé qui permet d'utiliser l'API Knowledge Graph (obtenue après activation de l'API dans la console de Google) ;
  • query indique les mots de la recherche à effectuer ;
  • languages permet de lister les langages de recherche à utiliser (par exemple « fr ») ;
  • limit indique le nombre maximum d'entités à retourner ;
  • types permet de spécifier les types Schema.org à conserver, comme Person, Event, Book (…) ;
  • ids donne la possibilité de lister des identifiants d'entités à analyser à l'aide d'un MID (Machine-generated Identifier) comme « /m/0dl567 » (pour Taylor Swift ici) ;
  • indent permet d'indenter le code JSON-LD retourné par l'API ;
  • prefix active un préfixe pour la recherche d'entités.

Pour chaque résultat répondant à une requête, à un type, à un ID (…), l'API Knowledge Graph attribue un ResultScore. Il s'agit d'une note de pertinence selon le contexte de recherche, et plus ce ResultScore est haut, plus l'entité correspond précisément à la requête. Les résultats sont classés de manière décroissante afin de faire naturellement ressortir les entités les plus pertinentes selon nos critères de recherche.

Mise en place de l'API avec Javascript

L'usage de l'API Knowledge Graph avec Javascript peut s'écrire de multiples manières. Nous avons fait le choix de l'utiliser avec jQuery afin de raccourcir l'écriture générale, tout en ajoutant un peu de CSS pour styliser les résultats.

L'accès à l'API est très simple comme vous pouvez le voir dans le code suivant. Nous avons effectué une recherche à propos d'Olivier Andrieu afin de savoir si le Knowledge Graph connaissait cette personne... Et bien c'est le cas ! Et nous obtenons même quatre résultats plus ou moins éloignés du sujet.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>API Knowledge Graph avec Javascript et jQuery</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script>
            var service_url = 'https://kgsearch.googleapis.com/v1/entities:search';
            var params = {
                       'key' : 'AIzaSyBttg9VquQmEWa5F3AEiBEZSx3toD0MH4U',
                       'query': 'Olivier Andrieu',
                       'languages': 'fr',
                       'indent': true,
            };

            jQuery.getJSON(service_url + '?callback=?', params, function(response) {
                       // Création d'un bloc pour la requête recherchée
                       jQuery("#result").append('<h1 class="entity-title">API Knowledge Graph</h1>');
                       // jQuery("#result").append('<p class="entity-query">Résultats pour la requête "'+params['query']+'"</p>');

            jQuery.each(response.itemListElement, function(i, value) {
                       console.log(value);
                       // Création d'un bloc par entité trouvée
                       jQuery("#result").append('<div class="entity-info info-'+i+'"></div>');

                       // Insertion des informations intéressantes
                       jQuery(".info-"+i).append('<strong>Entité : </strong><span class="entity-name">'+value['result']['name']+'</span><br/>');
                       jQuery(".info-"+i).append('<strong>MID : </strong><span class="entity-type">'+value['result']['@id']+'</span><br/>');
                       jQuery(".info-"+i).append('<strong>Type : </strong><span class="entity-type">'+value['result']['@type']+'</span><br/>');
                       jQuery(".info-"+i).append('<strong>ResultScore (pertinence) : </strong><span class="entity-score">'+value['resultScore']+'</span><br/>');
                       if(typeof(value['result']['description']) !== "undefined") {
                                   jQuery(".info-"+i).append('<strong>Description courte : </strong><span class="entity-desc">'+value['result']['description']+'</span><br/>');
                       }
                       if(typeof(value['result']['detailedDescription']) !== "undefined") {
                                   jQuery(".info-"+i).append('<strong>Description longue : </strong><span class="entity-description">'+value['result']['detailedDescription']['articleBody']+'</span><br/>');
                                   jQuery(".info-"+i).append('<strong>URL source : </strong><span class="entity-source">'+value['result']['detailedDescription']['url']+'</span><br/>');
                       }
                       });
            });
</script>
<style type="text/css">
* {margin:0; padding:0; font-size:1em;}
body {font-family:arial, helvetica, sans-serif;}
#result {margin:1em; padding:1em; background:#333; border-radius:5px;}
#result .entity-title {font-size:1.5em; color:#f1f1f1; text-align:center; margin-bottom:.2em;}
#result .entity-query {font-size:1.2em; color:#f1f1f1; text-align:center; margin-bottom:1.5em;}
#result .entity-info {background:#dadada; padding:1em; margin-bottom:1em;}
#result .entity-info:last-child {margin-bottom:0;}
</style>
</head>
<body>
<div id="result"></div>
</body>
</html>

La capture suivante montre les résultats affichés dans l'ordre de pertinence obtenu grâce au ResultScore du Knowledge Graph de Google. Les deux premiers résultats sont tout à fait pertinents puisqu'ils évoquent directement Olivier Andrieu ou un de ses (nombreux) ouvrages. En revanche, les deux derniers résultats existent car l'API a réussi à trouver la requête « Olivier Andrieu » au sein d'entités connues du Knowledge Graph. Si nous prenons le cas de « La philo selon Philippe » par exemple, cela est dû au fait que les mots « Andrieu » et « Olivier » se retrouvent associés, alors qu'il n'est nullement sujet de référencement ici. Il aurait fallu ajouter un paramètre « types » comme « Person » pour éviter ce genre de faux positif.


Fig.2. Résultats proposés par l'API Knowledge Graph pour « Olivier Andrieu ».

Javascript apporte ici toute sa souplesse. En effet, il est possible d'écrire le code de multiples manières, avec ou sans librairie comme jQuery, avec ou sans Ajax, avec ou sans événement utilisateur, avec ou sans NodeJS, etc. Il est donc possible de traiter les données comme bon nous semble.

Pour des raisons de lecture et de rapidité d'écriture, nous avons opté pour l'usage de jQuery. Il faut avouer que la librairie nous a donné la possibilité de considérablement raccourcir le code Javascript, mais également de le rendre plus lisible. En Vanilla Javascript (natif), le programme aurait presque doublé de volume, rendant le code bien moins lisible et pratique à utiliser. Javascript est donc à utiliser avec les bons outils si nous recherchons un code concis, lisible et facilement réutilisable par des tiers.

Le choix du Javascript devrait se faire si nous souhaitons créer une application qui souhaite afficher directement les résultats sur le Web. S'il s'agit uniquement d'un programme personnel utilisé pour vérifier si des entités existent, ce langage n'est pas une nécessité absolue.

La simplicité d'accès de l'API Knowledge Graph permet également d'utiliser le programme localement sur un ordinateur, à l'aide d'une simple connexion Internet. En revanche, d'autres API nécessitent d'utiliser le code sur un serveur avec Javascript, donc cet atout dépend vraiment des cas que nous rencontrerons…

Mise en place de l'API avec PHP

Comme pour Javascript, l'usage de PHP permet d'obtenir un programme prêt à l'emploi pour fonctionner sur le Web. Toutefois, PHP offre un peu moins de souplesse de code et doit s'utiliser obligatoirement côté serveur (ou avec un serveur local comme Xampp, Mamp ou Wamp). En effet, nous pouvons passer par la librairie Google PHP API Client, par une requête faite avec cURL ou file_get_contents(), mais cela reste bien moins fourni qu'avec Javascript.

Si nous cherchons à obtenir un résultat équivalent à celui offert par Javascript, un code court avec la fonction file_get_contents() est certainement la meilleure option, comme ceci :

<?php
$service_url = 'https://kgsearch.googleapis.com/v1/entities:search';
$params = array(
            'key' => 'AIzaSyBttg9VquQmEWa5F3AEiBEZSx3toD0MH4U',
            'query' => 'Olivier Andrieu',
            'languages' => 'fr',
            'indent' => true
);
$url = $service_url.'?'.http_build_query($params);

// Chargement de l'URL testée au départ
$contextOptions = array(
            "ssl" => array(
                       "verify_peer"      => false,
                       "verify_peer_name" => false,
            ),
);
$urlComplete = file_get_contents($url, false, stream_context_create($contextOptions));
$response = json_decode($urlComplete, true);

// Affichage des résultats en HTML, CSS et PHP
?>
<style type="text/css">
* {margin:0; padding:0; font-size:1em;}
body {font-family:arial, helvetica, sans-serif;}
#result {margin:1em; padding:1em; background:#333; border-radius:5px;}
#result .entity-title {font-size:1.5em; color:#f1f1f1; text-align:center; margin-bottom:.2em;}
#result .entity-query {font-size:1.2em; color:#f1f1f1; text-align:center; margin-bottom:1.5em;}
#result .entity-info {background:#dadada; padding:1em; margin-bottom:1em;}
#result .entity-info:last-child {margin-bottom:0;}
</style>
<div id="result">
            <h1 class="entity-title">API Knowledge Graph</h1>
            <p class="entity-query">Résultats pour la requête "<?php echo $params['query']; ?>"</p>
            <?php foreach($response['itemListElement'] as $element) { ?>
                       <div class="entity-info">
                                   <strong>Entité : </strong><span class="entity-name"><?php echo $element['result']['name']; ?></span><br/>
                                   <strong>MID : </strong><span class="entity-type"><?php echo $element['result']['@id']; ?></span><br/>
                                   <strong>Type : </strong><span class="entity-type"><?php echo implode(", ",$element['result']['@type']); ?></span><br/>
                                   <strong>ResultScore (pertinence) : </strong><span class="entity-score"><?php echo $element['resultScore']; ?></span><br/>
                                   <?php if(!empty($element['result']['description'])) { ?>
                                   <strong>Description courte : </strong><span class="entity-desc"><?php echo $element['result']['description']; ?></span><br/>
                       <?php } ?>
                       <?php if(!empty($element['result']['detailedDescription'])) { ?>
                                   <strong>Description longue : </strong><span class="entity-description"><?php echo $element['result']['detailedDescription']['articleBody']; ?></span><br/>
                                   <strong>URL source : </strong><span class="entity-source"><?php echo $element['result']['detailedDescription']['url']; ?></span><br/>
                       <?php } ?>
                       </div>
            <?php } ?>
</div>

Les résultats s'affichent exactement comme dans la Figure 2 sur la requête « Olivier Andrieu » et permettraient d'effectuer des traitements approfondis côté serveur pour traiter les données. Pour l'API Knowledge Graph, l'avantage de PHP est sûrement son confort de lecture sans avoir à passer par une bibliothèque externe comme jQuery avec Javascript.

Cela confère au programme un code plus léger, moins lourd et souvent un peu plus rapide à l'exécution (intéressant si des dizaines d'entités existent ou si nous souhaitons effectuer des actions multiples dans le code). Toutefois, il s'agit essentiellement de nuance dans le cas de cette API légère et nous devons essentiellement choisir selon notre aisance avec l'un des deux langages.

Sur des API plus complexes, PHP obtiendra très souvent un code plus lisible et rapide d'accès, mais pas nécessairement plus efficace à l'usage. Dans notre exemple, nous sommes passé directement par l'URL de l'API mais nous aurions également pu utiliser la librairie Google PHP API Client qui est très pratique quand l'API propose de nombreuses fonctionnalités. Dans ce type de cas, le code PHP qui en résulte est plus lisible que du Javascript.

Mise en place de l'API avec Python

Python est un langage différent des deux précédents, et ses objectifs d'utilisation ne doivent pas être identiques. En effet, Python est avant tout un langage informatique, et non un langage orienté Web. Par conséquent, il ne permet pas d'interagir directement avec une page HTML par simple « inclusion » comme du code PHP ou un script Javascript, il faudrait passer par des modules externes ou des CMS comme Django pour atteindre cet objectif.

Partant de ce constat, Python offre l'avantage d'être très rapide, et souvent exécuté en ligne de commande (CLI). Cependant, nous ne pouvons pas l'utiliser pour les mêmes applications que ses deux compères précédemment présentés. Par exemple, Google utilise Python dans l'intelligence artificielle ou pour crawler les résultats (même si ce n'est pas l'unique langage utilisé pour ces besoins). Dans ces deux cas, nul besoin d'interface web, mais juste des qualités de rapidité et d'efficience du langage. Une fois les données traitées ou remontées dans une base de données, ce sont des langages Web qui prennent le relais pour gérer les interfaces définitives. Ainsi, Python sert uniquement aux tâches de fond car il a des qualités énormes en ce sens, puis les autres langages font le reste…

Il a pour désavantage de ne pas avoir la même syntaxe selon que nous utilisons Python 2.x.x ou Python 3.x.x, c'est pourquoi nous faisons ici le choix d'écrire dans la dernière version du langage.

Prenons un exemple. L'API Knowledge Graph recense toutes les données sur les entités, l'intérêt de Python pourrait être de mener des requêtes en boucle sur des variantes données d'un sujet. Tout cela pourrait alors s'effectuer très rapidement pour enregistrer les informations dans un fichier ou une base de données, afin de traiter les résultats ultérieurement.

En ce qui nous concerne, nous allons conserver la même idée qu'avec les deux autres langages afin de comparer le code et voir les avantages et inconvénients de chacun. En Python, nous devons en outre utiliser des modules externes mais aussi bien gérer l'encodage des caractères, car nous allons créer un fichier HTML à la volée pour obtenir le même résultat qu'en Javascript et PHP. Par conséquent, cela rajoute quelques lignes, bien qu'il s'agisse malgré tout du code le plus simple et le plus lisible en définitive grâce à sa syntaxe légère.

import json
import urllib.parse, urllib.request
import webbrowser

service_url = 'https://kgsearch.googleapis.com/v1/entities:search'
params = {
    'key': "AIzaSyBttg9VquQmEWa5F3AEiBEZSx3toD0MH4U",
    'query': "Olivier Andrieu",
    'languages': 'fr',
    'indent': True,
}
url = service_url + '?' + urllib.parse.urlencode(params)
response = json.loads(urllib.request.urlopen(url).read())

# Affichage
message = '<meta charset="utf-8">'
message+= '<style type="text/css">'
message+= '* {margin:0; padding:0; font-size:1em;}'
message+= 'body {font-family:arial, helvetica, sans-serif;}'
message+= '#result {margin:1em; padding:1em; background:#333; border-radius:5px;}'
message+= '#result .entity-title {font-size:1.5em; color:#f1f1f1; text-align:center; margin-bottom:.2em;}'
message+= '#result .entity-query {font-size:1.2em; color:#f1f1f1; text-align:center; margin-bottom:1.5em;}'
message+= '#result .entity-info {background:#dadada; padding:1em; margin-bottom:1em;}'
message+= '#result .entity-info:last-child {margin-bottom:0;}'
message+= '</style>'
message+= '<div id="result">'
message+= '<h1 class="entity-title">API Knowledge Graph</h1>'
message+= '<p class="entity-query">Résultats pour la requête "'+str(params['query'])+'"</p>'

# Création d'un fichier HTML pour enregistrer les résultats
f = open('api-knowledge-graph-python.html', 'wb')

# Boucle des résultats
for element in response['itemListElement']:
            message+= '<div class="entity-info">'
            message+= '<strong>Entité : </strong><span class="entity-name">'+str(element['result']['name'])+'</span><br/>'
            message+= '<strong>MID : </strong><span class="entity-type">'+str(element['result']['@id'])+'</span><br/>'
            message+= '<strong>Type : </strong><span class="entity-type">'+str(", ".join(element['result']['@type']))+'</span><br/>'
            message+= '<strong>ResultScore (pertinence) : </strong><span class="entity-score">'+str(element['resultScore'])+'</span><br/>'
            if 'description' in element['result']:
                       message+= '<strong>Description courte : </strong><span class="entity-desc">'+str(element['result']['description'])+'</span><br/>'
            if 'detailedDescription' in element['result']:
                       message+= '<strong>Description longue : </strong><span class="entity-description">'+str(element['result']['detailedDescription']['articleBody'])+'</span><br/>'
                       message+= '<strong>URL source : </strong><span class="entity-source"><'+str(element['result']['detailedDescription']['url'])+'</span><br/>'
            message+= '</div>'

# Ecriture et fermeture du message
f.write(message.encode("utf-8"))
f.close()

# Ouverture de la page HTML générée dans un nouvel onglet
webbrowser.open_new_tab('api-knowledge-graph-python.html')

Pour utiliser ce code, il faut avoir Python 3.x.x installé sur son ordinateur (source : https://www.python.org) et enregistrer ce code dans un fichier. Pour l'exemple, nous l'appellerons « API-Knowledge-Graph.py ». Enfin, il ne reste qu'à lancer une fenêtre de commande (terminal Linux, PowerShell sur Windows 10, etc) dans le même dossier que le fichier créé avec la commande « py API-Knowledge-Graph.py ». Une simple validation va lancer le programme, créer un fichier HTML et l'ouvrir dans le navigateur (cela fonctionne sans problème avec Mozilla Firefox et d'autres navigateurs d'après la documentation).

Le programme s'exécute très rapidement avec Python et génère la page HTML à la volée en un rien de temps. Cela démontre les qualités de rapidité de Python, et encore, notre programme n'est pas un parfait exemple qui traite des volumes de données importants. En générant une page web, nous pouvons contourner en partie le fait que Python n'interagit pas avec des pages existantes, mais rappelons-nous qu'il ne s'agit pas de son rôle principal.

Conclusion sur le choix du langage

L'API Knowledge Graph nous a permis de présenter les différents usages de Javascript, PHP et Python pour un même exemple. Dans notre cas, seules quelques lignes de code distinguent les trois programmes car nous avons souhaité obtenir le même résultat en HTML.

Dans les faits, Python reste le langage le plus rapide et le plus court sur les trois proposés. En revanche, son usage est davantage limité à du traitement de données, et n'a pas un intérêt fondamental dans bien des cas. Javascript, quant à lui, est très polyvalent, mais n'est justement pas excellent pour du traitement de données. Il a plutôt un rôle d'affichage en adéquation avec des actions d'utilisateurs dans une application. PHP se retrouve au milieu de tout cela car il permet de bons traitements rapides tout en étant intégrables dans des pages Web.

Idéalement, il conviendrait de traiter les gros volumes de données avec Python, puis de les enregistrer en XML, JSON ou dans une base de données par exemple. Ensuite, Javascript (ou PHP) pourrait être utilisé pour créer une application ergonomique pour les usagers. Si nous prenons l'exemple de Google Analytics, nous pourrions notamment traiter rapidement les multitudes de données avec Python puis recréer une interface accessible avec Javascript. Il ne nous reste plus qu'à travailler, alors ? 🙂


Mathieu Chartier
Consultant-Formateur et webmaster indépendant, Internet-Formation (https://www.internet-formation.fr)