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.
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.
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.
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/')
...
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 :
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.
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.
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/Emailform["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.
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
Nous venons donc de voir comment interagir avec un site internet grâce à Mechanize pour :
Nous allons nous attarder dans cette dernière partie sur la manière de 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.
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.
Cet outil peut être d’une très grande utilité et rendre des tâches quotidiennes complètement automatique :
L’équipe Synbioz.
Libres d’être ensemble.