Aller au contenu

Introduction à l'utilisation de Selenium.

Selenium est un outil d’automatisation open source pour tester des applications web. Je vais vous montrer comment je l’ai mis en oeuvre pour automatiser l’envoi de kudos sur Strava. Pour ceux qui ne connaissent pas Strava, Strava est un réseau social à destination des sportifs. Strava permet d’avoir un suivi de ses activités sportives : randonnée, cyclisme, course à pied, natation, etc. Les kudos sont des encouragements que l’envoie aux sportifs que l’on follow. Avec 250 personnes suivies cela devient vite fastidieux. C’est pourquoi j’ai décidé de l’automatiser.

Pour cela j’utilise un de mes raspberry Pi 3B+ sur lequel j’ai installé une raspbian lite comme système d’exploitation.

Installation des librairies python et du driver selenium pour chromium

Il suffit d’installer deux librairies: Selenium et pyvirtualdisplay pour émuler un écran et donc faire tourner sans écran ce petit bout de code. Il faut aussi installer le driver permettant à selenium de contrôler Chromium.

Terminal window
sudo apt install chromium-browser chromium-chromedriver xvfb python3-pip
pip3 install selenium pyvirtualdisplay --user

Commençons à écrire le code:

from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
from pyvirtualdisplay import Display, display
def main():
display = Display(visible=0, size=(2880, 1800)).start()
driver = driver_init()
driver.get("https://www.strava.com/login")
driver.save_screenshot('screenshot.webp')
driver.quit()
display.stop()
def driver_init():
options = webdriver.ChromeOptions()
options.add_argument("--headless")
options.add_argument("--disable-gpu")
driver = webdriver.Chrome(options=options)
return driver
if __name__ == "__main__":
main()

Donc dans un premier temps on initialise un écran virtuel de taille 2880x1800 pixel que l’on démarre. Ensuite on lance chrome via la fonction driver_init avec les options headless et disable-gpu. On ouvre la page de login de strava et histoire de se rassurer on prend une capture d’écran. Pour finir on ferme chrome et on éteint l’écran. Plutôt simple non ?

Maintenant voyons comment se connecter sur Strava.

from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
from pyvirtualdisplay import Display, display
def main():
display = Display(visible=0, size=(2880, 1800)).start()
driver = driver_init()
driver.get("https://www.strava.com/login")
email_field = driver.find_element_by_xpath('//*[@id="email"]')
password_field = driver.find_element_by_xpath('//*[@id="password"]')
email = 'nom@gmail.com'
password = 'toto'
email_field.send_keys(email)
password_field.send_keys(password)
driver.find_element_by_xpath('//*[@id="login-button"]').click()
driver.save_screenshot('screenshot.webp')
time.sleep(2)
driver.quit()
display.stop()
def driver_init():
options = webdriver.ChromeOptions()
options.add_argument("--headless")
options.add_argument("--disable-gpu")
driver = webdriver.Chrome(options=options)
return driver
if __name__ == "__main__":
main()

Il suffit de rechercher les zones de texte possédant les id ‘email’ et ‘password’ avec la fonction find_element_by_xpath du driver. Ensuite on envoie les informations de connexion avec la fonction send_keys. On clique ensuite sur le bouton possédant l’id ‘login-button’ avec la fonction click.

Pour retrouver les ids il suffit d’utiliser le debugger de chrome ou de firefox. Sur chrome sur l’élément à analyser cliquer sur le menu Inspecter.

Chrome Inspection

On est connecté maintenant voyons comment envoyer des kudos.

from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
from pyvirtualdisplay import Display, display
def main():
display = Display(visible=0, size=(2880, 1800)).start()
driver = driver_init()
driver.get("https://www.strava.com/login")
email_field = driver.find_element_by_xpath('//*[@id="email"]')
password_field = driver.find_element_by_xpath('//*[@id="password"]')
email = 'nom@gmail.com'
password = 'toto'
email_field.send_keys(email)
password_field.send_keys(password)
driver.find_element_by_xpath('//*[@id="login-button"]').click()
driver.save_screenshot('screenshot.webp')
time.sleep(2)
driver.get("https://www.strava.com/dashboard/activity/160")
screen_height = driver.execute_script("return window.screen.height;") * 4
i = 0
while True:
print ('scroll page ...')
driver.execute_script("window.scrollTo(0, {screen_height}*{i});".format(screen_height=screen_height, i=i))
i += 1
time.sleep(5)
scroll_height = driver.execute_script("return document.body.scrollHeight;")
if (screen_height) * i > scroll_height or i > 15:
break
kudoable_items = []
solo_rides = driver.find_elements_by_xpath("//button[contains(@class,'KudosAndComments--social-button--1QAOS')]")
for ride in solo_rides:
title = ride.get_attribute("title")
if title in["Give kudos", "Be the first to give kudos!"]:
kudoable_items.append(ride)
for item in kudoable_items:
try:
driver.execute_script("arguments[0].click();", item)
print("", end='', flush=True)
time.sleep(random.uniform(2.5, 5))
except NoSuchElementException:
print(".", end='', flush=True)
driver.quit()
display.stop()
def driver_init():
options = webdriver.ChromeOptions()
options.add_argument("--headless")
options.add_argument("--disable-gpu")
driver = webdriver.Chrome(options=options)
return driver
if __name__ == "__main__":
main()

En fait je demande à selenium de reproduire ce que je fais manuellement. J’affiche le dashboard Strava et je scroll l’écran jusqu’à ce que Strava arrête d’afficher des nouvelles activités. Je clique ensuite sur tous les boutons ayant comme titre “Give kudos” ou “Be the first to give kudos!”.

Pour faire défiler la page j’ai écris une simple boucle qui fait défiler la page de 4 fois la hauteur de l’affichage. J’ai limité l’opération à 15 répétitions (le compteur i).

Je recherche toujours avec la fonction find_elements_by_xpath tous les boutons possédant la classe ‘KudosAndComments—social-button—1QAOS’ que je filtre ensuite sur le titre. Une fois filter on clique. J’ai mis des tempos car Strava détecte les applications de scraping.

Et voila y a plus qu’à.