Go to Hackademy website

Automatiser vos interactions avec une application web

Guillaume Goureau

Posté par Guillaume Goureau dans les catégories back

Aujourd’hui je vous propose de réaliser une petite application qui va se connecter à un site et qui va aller télécharger un fichier. Le meilleur dans l’histoire c’est que tout cela va se faire automatiquement sans que vous ayez à lever le petit doigt. De la magie ? Non, nous devons cela à la gem Mechanize que je vais vous présenter sans plus attendre.

Mechanize

La bibliothèque Mechanize va nous permettre d’interagir automatiquement avec un site internet. Elle permet de stocker et d’envoyer automatiquement des cookies, suivre des redirections, soumettre des formulaires ou encore garder une trace des sites que vous avez visité.

Mechanize utilise Nokogiri pour interagir avec les sites et analyser les pages afin de simplifier leur manipulation. Je vous invite à lire cette documentation qui vous sera très utile si vous voulez aller plus loin avec Mechanize. Passons directement à la pratique.

Mise en place

Création de l’application Rails

Dans un premier temps nous allons créer un nouveau projet Rails.

rails new demo_mechanize

Nous allons à présent ajouter la gem mechanize

# Dans le fichier Gemfile
gem 'mechanize', '~> 2.7.3'

Notre application Rails est maintenant prête à l’utilisation. Nous allons passer à la première partie de développement : la connexion à un site internet.

Connexion à un site internet

Pour se connecter à un site web, nous allons dans un premier temps créer une nouvelle tâche rake. Pour cela nous allons créer un nouveau fichier dans lequel nous allons travailler tout au long de cet article :

# lib/tasks/github.rake
namespace :github do
  desc 'Connection to the web site'
  task connection: :environment do
    # Mettre ici le code de la partie connexion à un site internet
  end
end

Pour accéder à une page internet, nous allons utiliser la méthode d’instance de page de Mechanize qui va nous retourner une instance Mechanize::Page. Pour cela nous allons initialiser Mechanize puis faire appel à la méthode get.

...
agent = Mechanize.new
home_page = agent.get('https://github.com/')
...

Changer de page

Maintenant que nous avons notre instance de la page d’accueil de github, nous devons cliquer sur le bouton “Sign in”. Pour cela il faut identifier le lien “Sign in”. Nous allons donc inspecter la page et voir ce qu’il en retourne :

mechanize-inspection

Nous pouvons observer que le lien est composé de texte et de ce fait nous allons pouvoir l’utiliser pour trouver ce dernier.

Si cela n’est pas le cas, par exemple que le lien est composé d’une image où il est écrit “Sign in”, alors il vous faudra utiliser d’autres éléments tel que l’id du lien, si il existe, ou encore le href pour retrouver celui-ci.

À noter que dès lors que votre élément utilise un id vous devriez l’utiliser car celui ci a vocation à être unique dans le DOM et limite donc le risque de se tromper d’élément ciblé.

Retournons à notre code et faisons cliquer notre programme sur le lien “Sign In”

...
signin_page = agent.click(home_page.link_with(text: "Sign in"))
...

Que venons nous de faire ? home_page.link_with(text: "Sign in") va nous permettre de retourner le lien qui se trouve sur la page home contenant le texte “Sign In”. agent.click va simplement cliquer sur l’élément et nous retourner une nouvelle instance d’une nouvelle page (la page où nous aurons été redirigé après avoir cliqué sur le lien).

Comme vu juste plus haut, nous utilisons text: pour trouver ce lien. Cela aurait pu être href: en spécifiant /login si nous ne disposions pas du texte.

Mechanize offre différentes méthodes très utiles telles que home_page.links qui va vous permettre de retourner la liste des liens disponibles sur cette page.

Je vous invite à jeter un œil sur cette documentation qui donne plein de petites astuces.

Soumettre un formulaire

Maintenant que nous nous trouvons sur la page de connexion, il nous faut remplir le formulaire et le soumettre.

Pour cela nous allons de nouveau inspecter la page. Sur cette page nous allons trouver deux formulaires. Un premier formulaire qui est celui du champ de recherche et un second qui est le formulaire de connexion qui nous intéresse.

mechanize-form

Il nous faut dans un premier temps trouver un moyen d’identifier notre formulaire car nous en avons deux présents sur cette page. Pour cela nous allons utiliser action="/session" de ce dernier pour l’identifier.

Dans un second temps il nous faut identifier les différents champs du formulaire. Pour notre cas chaque champ dispose d’un attribut name. login pour le champ “Username or Email” et password pour le champ “Password”

...
my_page = signin_page.form_with(action: "/session") do |form|
  form["login"]  = "user@example.com"
  form["password"] = "password"
end.submit
...
  • signin_page.form_with(action: "/session") va nous permettre de retrouver le formulaire qui possède action="/session" sur la page de connexion.
  • form["login"] va nous permettre de renseigner le champ du nom d’utilisateur/Email
  • form["password"] va nous permettre de renseigner le champ du mot de passe.
  • .submit va nous permettre de soumettre notre formulaire et va nous retourner une nouvelle instance de page, qui sera la page où nous aurons été redirigé après avoir soumis le formulaire.

Une autre méthode aurait été d’utiliser signin_page.forms qui liste les formulaires de la page ou nous nous trouvons. Étant donné que notre formulaire se trouve juste après celui de recherche, nous aurions pu écrire :

...
form = signin_page.forms[1]
form["login"]  = "user@example.com"
form["password"] = "password"
form.submit
...

Nous venons de soumettre notre formulaire mais cela a-t-il marché ? Pour vérifier que nous sommes bien identifié, nous allons simplement rechercher sur la page si nous pouvons accéder à notre profil utilisateur.

mechanize-profil

Pour ce faire nous allons utiliser le href du lien qui nous permet d’accéder à notre profil.

...
if my_page.link_with(href: "/username")
  puts "vous êtes connecté"
else
  puts "Vous n'avez pas réussi à vous connecter"
end
...

Nous pouvons exécuter notre tâche rake et vérifier qu’elle fonctionne.

rake github:connection

Conclusion

Nous venons donc de voir comment interagir avec un site internet grâce à Mechanize pour :

  • changer de page
  • soumettre un formulaire
  • se connecter à un site

Nous allons nous attarder dans cette dernière partie sur la manière de télécharger un fichier.

Télécharger un fichier

Nous allons dans cette partie télécharger le tuto que nous sommes entrain de réaliser disponible sur notre github.

Nous allons dans un premier temps créer une nouvelle tâche rake.

# lib/tasks/github.rake
namespace :github do
  desc 'Download file'
  task download: :environment do
    # Mettre ici le code de la partie télécharger un fichier
  end
end

Puis nous allons initialiser Mechanize et retourner l’instance de la page de notre dépôt.

...
agent = Mechanize.new
home_page = agent.get('https://github.com/synbioz/demo_mechanize')
...

Pour télécharger ce tuto, il nous faut cliquer sur le bouton “Download ZIP”. Inspectons la page.

mechanize-download

Nous allons cette fois ci utiliser href="/synbioz/demo_mechanize/archive/master.zip" pour localiser le lien sur la page.

...
agent.click(home_page.link_with(href: "/synbioz/demo_mechanize/archive/master.zip")).save_as Rails.root.join("demo_mechanize.zip")
...

La première partie de ce code est du même principe que ce que nous avons vu précédemment. Nous avons juste rajouté .save_as Rails.root.join("demo_mechanize.zip").

Étant donné que le lien sur lequel nous voulons cliquer va nous rediriger vers le fichier que nous voulons télécharger, nous n’avons plus qu’a le sauvegarder à l’emplacement voulu. Dans cette exemple, il sera sauvegardé sous le nom de demo_mechanize.zip à la racine de ce projet.

Nous pouvons exécuter notre tâche rake :

rake github:download

Et retrouver le fichier zip de notre tutoriel à la racine de notre projet.

Conclusion

Cet outil peut être d’une très grande utilité et rendre des tâches quotidiennes complètement automatique :

  • télécharger des archives
  • remplir des formulaires
  • interagir sur des sites
  • récupérer des informations qui ne sont pas disponibles par le biais d’une API
  • ou encore pour les plus geeks d’entre vous, automatiser des tâches sur des jeux on-line sur navigateur

L’équipe Synbioz.

Libres d’être ensemble.

Articles connexes

Une brève histoire d'Elixir et Erlang/OTP

31/01/2019

Je développe depuis plusieurs années en Ruby. Depuis mon arrivée chez Synbioz, j’expérimente en plus avec Elixir de façon assez naturelle. En quoi Elixir est-il différent, me demanderez-vous ? Pour...

Écrire une thread pool en Ruby

10/01/2019

Pouvoir exécuter plusieurs tâches en parallèle, que ce soit dans un script ou une application, peut être vraiment très utile, surtout dans le cas où le traitement de ces tâches peut être très long....

Translation temporelle

31/05/2018

Cette semaine, je me suis essayé à un nouveau format d’article qui se présente sous la forme d’une nouvelle de Science-Fiction. Je tiens en passant à remercier Valentin pour ses illustrations....

Authentifier l'accès à vos ressources avec Dragonfly

11/05/2017

Pour ceux qui ne connaissent pas Dragonfly, c’est une application Rack qui peut être utilisée seule ou via un middleware. Le fait que ce soit une application Rack la rend compatible avec toutes les...