Logo JavaScript

PhantomJS, chargez et jouez avec vos sites en JS sans quitter la console

Flattr this!

"Uh ?!"

C'est un peu près la seule chose que j'ai été foutu de dire quand on m'a parlé la première fois de PhantomJS. Après j'ai sorti mon gourdin et j'ai tapé sur la boite comme un dégénéré.

homme_prehistoire_gourdin

Jusqu'à ce que je comprenne que ce n'était pas à manger mais bien un outil qui allait sérieusement améliorer l'efficacité de l'équipe SEO de ma boite. Tout de suite, l'image de l'homme préhistorique débile parait plus fun.

Plus sérieusement ?

Alors PhantomJS, c'est tout simplement, un outil qui va interpréter un de vos scripts JS pour aller chercher par exemple une page web et vous permettre de la manipuler sans jamais quitter votre ligne de commande. En fait, il y a une sorte de navigateur QT qui permet de ne pas ouvrir de navigateur tout en faisant le même boulot. Il est donc capable de charger les images, scripts et CSS. Ainsi que de les exécuter parfaitement normalement. J'ai pas bien compris cette partie là, j'espère avoir l'occasion de mieux me pencher dessus. Si quelqu'un peut m'expliquer, je suis preneur 😉

Ce que j'ai compris par contre, c'est que si je fais ça :

var page = require('webpage').create();
var url = 'http://www.mathieurobin.com/';
page.open(url, function (status) {
    console.log(status); // 'success' or 'fail'
    phantom.exit();
});

J'obtiens de suite la disponibilité de ma page. Et ça ça me parle. Sauf que ça parait un peu limité si c'est que ça. cURL fait mieux et en moins de ligne. Donc allons plus loin.

J'en veux plus !

Dans ma boite (Companeo), on s'occupe de tout un tas de sites (environ 300). Le problème auquel je me suis attaqué est de pouvoir connaitre à tout moment la disponibilité de tout ces sites, si leur version de WordPress est à jour, si ils chargent toujours dans un délai respectable et enfin si il n'y a pas d'erreur JS ou de chargement de ressources.

J'en vois au fond de la salle qui lèvent la tête, curieux. Et c'est normal. Un tel script, c'est du pain béni pour s'assurer que vos sites fonctionnent sans même avoir à y aller. Ce script a sûrement été créé en centaines d'exemplaires de par le monde. Je l'ai moi aussi développé. Il est surement plus que perfectible mais me permet de contrôler tout ça après 3 minutes d'exécution environ (pour ces 300 sites). Le tout en moins de 100 lignes de code :

Ne reste plus qu'à exécuter ce script avec phantom et expédier la sortie standard dans un fichier HTML. Je ne vais pas rentrer dans le détail, mais ces sites chargent obligatoirement un fichier JS qu'on appelle "api". Je peux vérifier assez simplement que le script a bien été chargé. Pour la démo, nous allons tester le site "assurances risques pro".

Merci de ne pas hurler sur la conception de ce code. Aucun intérêt à la qualité de code. Côté bugs, le seul risque, c'est que si ça crashe sur un site, soit je le sais en console, soit ça se vautre encore plus violent au point d'embarquer aussi le script. Comme ça je sais quand même qu'il y a un souci. Et pour la démo de code, je n'ai laissé qu'un seul site. Histoire de ne pas polluer le gist.

Quoi d'autre ?

Je vois venir les petits malins, vous auriez pu faire pareil avec un zabbix ou un nagios, peu d’intérêt. Je dirais presque pareil et honnêtement, en polluant bien le code (hum les bons petits tags nagios qui se baladent). Sauf qu'avec PhantomJS, vous avez accès à un réel contrôle de la page, vous pouvez ordonner des choses à l'outil qui les exécutera dans la page, suivra la navigation, etc. Par exemple, vous pourrez "cliquer" sur un lien en scriptant en JS ce clic. Ou encore faire une requête de sélection d'éléments avec jQuery.

Vous pouvez même demander à PhantomJS de prendre une capture d'écran de la page. Génial non quand vous êtes dans votre ligne de commande et que vous n'avez pas eu à ouvrir de navigateur.

PhantomJS est tellement complet qu'il a même été intégré à Yeoman. Je n'utilise pas encore ce dernier dans ces moindres fondements mais je commence à maîtriser les différents outils qui le compose. Ça vaut le détour.

Bonus

Je vous ferai un topo sur CasperJS dès que j'en aurai l'occasion mais ceci est un autre outil basé sur PhantomJS qui lui est pour moi, le digne successeur, le remplaçant de Selenium. Le temps de mettre vraiment la tête dedans et de voir ce qu'il a dans le ventre.

Second bonus

Pour me simplifier la vie, j'ai intégré mes scripts PhantomJS (j'en ai fait plusieurs pour d'autres trucs) directement dans les scripts de cron/tests de l'application de mon travail. Comme ça, je peux même les lancer depuis l'interface de PhpStorm au besoin et de façon automatique quotidienne. Sans ouvrir de navigateur ni un terminal. Là ce n'est même plus de l'efficacité, c'est carrément du vice 😉

Le bonus ultime

La documentation est complète et bien faite. Il y a beaucoup d'exemples en tout genre aussi. Autrement dit, c'est prêt pour un réel usage industrialisé.

Côté licence

PhantomJS est sous licence BSD. Vous avez donc les mains très libres 😉

yatta

 

PS : je me diversifie, j'ajoute des petites images maintenant 😉

Flattr this!

A propos de Mathieu

Ingénieur développeur web dans la vente par correspondance B2B, adepte de nouvelles technologies et d'innovation. Vous pouvez aussi me retrouver sur Twitter @mathrobin
Cette entrée a été publiée dans JavaScript, avec comme mot(s)-clef(s) , , , , . Vous pouvez la mettre en favoris avec ce permalien.
  • Julien

    En effet PhantomJS est une application (un binaire) Qt qui embarque une version spécifique de webkit avec une API JS pour piloter le browser et interagir avec la page.

    • http://www.mathieurobin.com/ Mathieu

      Merci pour les explications :)

  • http://www.mickael-andrieu.fr mickael andrieu

    :) En effet c’est une tuerie phantomJs (merci pour le partage).

    CasperJs est un outil puissant, et très accessible, je te tanne depuis un certain temps pour que tu le bricoles donc j’insiste pas là dessus :p

    Le seul truc qui manquerait à Casper/Phantom(js) pour remplacer selenium c’est un port js pour la syntaxe Gerkin complètement intégré (à la manière d’un cucumberjs il me semble ?)

    Après, j’en demande surement trop :)

    • http://www.mathieurobin.com/ Mathieu

      Et je t’ai promis que l’article sur Casper arrivera asap 😉
      Gherkin tu veux dire ? J’aime pas trop la syntaxe, trop « littérale ». Mais oui, elle est plus accessible pour les gens qui ne savent pas coder.

  • Benjamin

    PhantomJS est un headless browser : donc on sépare la moteur de rendu, et l’affichage. PhantomJS va alors traiter uniquement la partie moteur de rendu. Il se base sur une version de WebKit qui est embarqué avec Qt4. Il prend en charge certains éléments de HTML5 mais pas tous (notamment la notion de click sur tout élément du DOM est absent de Phantom).

    Il existe plein de projet autour de phantom, notamment pour faire du test. Quand on y a gouté, on ne ppeut plus s’en passer.

    • http://www.mathieurobin.com/ Mathieu

      Merci pour les explications :)

  • https://github.com/laurentj/slimerjs Laurentj

    Et il y a son cousin, SlimerJS, qui repose sur Gecko (moteur de Firefox) plutôt que webkit (et il n’est pas encore headless mais sur linux/mac, avec xvfb, no souci, on peut le rendre headless). Son API sera 100% compatible avec PhantomJS. Pour le moment, c’est pas 100%, mais ton script devrait fonctionner 😉

    • http://www.mathieurobin.com/ Mathieu

      Histoire de multiplier les chances d’avoir tout bien fait et de détecter les potentiels bugs. Là ça sera royal^^ Merci de l’info !

  • Chris

    J’ai testé PhantomJS et CasperJS dans le cadre de tests et je peux dire que c’est tout simplement merveilleux !
    Je ne vais pas répéter ce qui a déjà été dit, il s’agit d’un navigateur headless, mais juste préciser qu’on peut absolument tout simuler via des scripts JS : remplissage de formulaire, clic, déplacement souris, drag&drop, etc …
    On peut tester les pages « dans leur contexte » c’est à dire avec leur propres scripts ou en inclure des supplémentaires, on peut donc inclure des plugins de type Mockjax (particulièrement utile pour isoler les tests), etc … bref, j’ai fait pas mal de tests avec et j’avoue qu’à aucun moment je me suis dit qu’il manquait quelque chose.

  • Romain

    Merci du partage, c’est effectivement très puissant !
    Je m’en suis inspiré pour tester l’appel à un pixel et ça marche plutôt pas mal à part parfois un décalage qui se créé dans les lignes.
    Par exemple : pour la ligne 4, j’ai la bonne URL mais rien en face et à partir de la ligne 5, j’ai dans les colonnes de gauche, les appels de l’URL de la ligne du dessus.
    As-tu déjà constaté la même chose ? Y vois-tu une explication possible ?
    Merci!

  • Romain

    Edit -> j’ai trouvé d’où venait le problème : les tags que je voulais surveiller étaient async et du coup ils étaient parfois chargés après le callback de chargelent de la page elle-même.
    Seule solution a priori ajouté un timeout dans la fonction result_current pour laisser plus de temps aux tags pour se déclencher
    cf http://stackoverflow.com/questions/11340038/phantomjs-not-waiting-for-full-page-load

  • http://videos-mdr.com Xavier

    Merci pour cet article. Je connaissais PhantomJS, mais pas casperJS, nous utilisons encore Selenium dans ma boite. On essaie de mettre en place des tests Jasmine.js pilotés par Karma en utilisans PhantomJS. Il me reste à trouver comment catcher les requêtes HTTP générées par nos scripts pour les analyser et à pouvoir lancer tout cela sur mobile. J’ai pas encore trouvé comment faire, mais ça semble jouable. Si ça parle ou intéresse quelqu’un, on peut en discuter.

    • http://www.mathieurobin.com/ Mathieu

      Salut,

      Si ton archi est bien conçue, normalement, un seul de tes composants faits réellement des requêtes AJAX. Les autres ne font que des appels à ce « proxy » d’une façon ou d’une autre. Ce qui te permet du coup d’isoler via un mock toute cette partie là. Après ça c’est pour la théorie, dans la pratique, on trouve régulièrement des cas où on ne s’est pas posés cette question et alors là, paye ta galère.

      Si tu utilises AngularJS, je te conseille $HttpBackEnd fourni avec, pour jQuery, Mootools ou encore YUI, il y a MockJax. Si tu utilises autre chose, désolé, là comme ça de tête, j’ai pas.

  • Franxoois

    Merci.
    L’article pointe sur http://www.phantomjs.org/
    Ce lien ne fonctionne pas chez moi. Ne serait ce pas plutôt http://phantomjs.org/ ?

    • http://www.mathieurobin.com/ Mathieu

      En effet, c’est corrigé, merci !

  • Johnny57

    Bonjour,

    Je recherche une solution pour interpréter le javascript avec php/curl. Phantomjs permet-il d’y parvenir ?

Articles liés