Si tu es en train de me lire, deux choses sont sûres, t’es un geek dans l’âme, et tu ne dis jamais non à un petit défi de programmation. Hé bien ça tombe bien parce qu’on va parler du jeu Morpion de Google (aussi appelé tic-tac-toe) ! Un véritable easter egg de Google qui apparaît dans les résultats de recherche. En cherchant tu peux aussi trouver d’autres jeux comme le solitaire.
Pourquoi Google nous offre-t-il ce cadeau de geek ?
Google est aussi le roi des « rich snippets« , ces petits plus qui te facilitent la vie direct dans les résultats de recherche. C’est le cas de notre Morpion, qui apparaît quand tu tapes « jeu Morpion » (parfois tu dois préciser « Google ») dans la barre de recherche et qui a été introduit le 27 août 2016. Pourquoi ? Parce que Google est cool, voilà tout.
Ok, mais comment ça fonctionne le Morpion ?
Google utilise des extraits enrichis pour ce faire. En gros, t’as une petite interface interactive qui te permet de jouer contre un ordinateur pas très futé ( enfin … si tu met en « impossible », c’est vraiment impossible). Puis tu clic tout simplement.
Créer un bot avec Python et Selenium pour jouer en mode automatique au jeu de morpion Google
Allez, maintenant, le fun commence ! Si tu te sens d’humeur hacker, pourquoi ne pas automatiser cette petite partie de Morpion ? T’emballe pas non plus, on reste dans le légal ! C’est juste pour le fun et la gloire.
Quels modules Python installer pour créer ce bot ?
import os from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.action_chains import ActionChains from selenium.common.exceptions import ElementClickInterceptedException, TimeoutException, NoSuchElementException from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC import time
A quoi servent toutes ces dépendances ?
1. import os
Alors, os
c’est un module en Python qui te donne accès à des fonctionnalités dépendantes du système d’exploitation. « Genre quoi ? » me demanderas-tu. Eh bien, ça peut être pour manipuler les chemins de fichiers, les variables d’environnement, et plein d’autres trucs utiles quand tu bosses sur un botQu'est-ce qu'un bot ? Un bot, c'est comme un petit génie du....
2. from selenium import webdriver
webdriver
, C’est le cœur de notre botQu'est-ce qu'un bot ? Un bot, c'est comme un petit génie du.... Selenium
, c’est une librairie en Python qui permet de contrôler un navigateur web comme si c’était toi derrière le clavier et la souris. Et webdriver
, c’est le composant qui te permet de dire « Hé, navigateur, ouvre cette page, clique ici, remplis ce formulaire ». Bref, sans webdriver
, pas de fiesta !
3. from selenium.webdriver.common.by import By
Ici, By
est un petit outil bien pratique pour dire à Selenium comment tu veux sélectionner les éléments sur la page web. « Je veux cliquer sur le bouton dont l’id est ‘play' ».
4. from selenium.webdriver.common.action_chains import ActionChains
ActionChains
c’est la classe qui va te permettre de faire des actions un peu plus complexes, comme du glisser-déposer, ou des séquences d’actions. « Je veux cliquer, attendre 3 secondes, puis taper du texte ». ActionChains
est ton meilleur pote pour ça.
5. from selenium.common.exceptions import ElementClickInterceptedException, TimeoutException, NoSuchElementException
On entre dans le vif du sujet ! Ces trois exceptions sont là pour gérer les petits pépins qui peuvent survenir. Un élément qui ne peut pas être cliqué (ElementClickInterceptedException
), une action qui prend trop de temps (TimeoutException
), ou un élément introuvable (NoSuchElementException
). Avec ces exceptions, ton botQu'est-ce qu'un bot ? Un bot, c'est comme un petit génie du... est prêt à affronter les imprévus !
6. from selenium.webdriver.support.ui import WebDriverWait
WebDriverWait
, c’est un peu le Gandalf de ton code. « Tu ne passeras pas… tant que l’élément n’est pas chargé ! » C’est un moyen d’attendre qu’un élément soit prêt avant de continuer. Pas de précipitation, on attend que tout soit en place !
7. from selenium.webdriver.support import expected_conditions as EC
Ici, expected_conditions
(qu’on abrège en EC
parce qu’on est des flemmards), c’est une collection de conditions prêtes à l’emploi pour WebDriverWait
. « Attends que le bouton soit cliquable », « Attends que l’élément soit visible ». EC
est là pour te faciliter la vie.
8. import time
Et enfin, time
. Ce vieux module Python est là pour gérer tout ce qui est en rapport avec le temps. Besoin de faire une petite pause dans ton code ? time.sleep(1)
et voilà, une seconde de répit. Parce que parfois, même un botQu'est-ce qu'un bot ? Un bot, c'est comme un petit génie du... a besoin de souffler au cas ou tu savais pas !
Le code source du bot détaillé
Définir une fonction pour prendre des captures d’écran
def take_screenshot(driver, name):
Ici, on crée une fonction appelée take_screenshot
. Elle prend deux paramètres : driver
, qui est notre navigateur automatisé, et name
, le nom qu’on veut donner à notre capture d’écran.
Préparer le dossier de destination
screenshot_folder = "screenshots" if not os.path.exists(screenshot_folder): os.makedirs(screenshot_folder)
On définit un dossier pour stocker nos captures d’écran, et on le crée s’il n’existe pas déjà. Comme ça, toutes nos captures seront bien rangées au même endroit.
Prendre la capture d’écran et la sauvegarder
driver.save_screenshot(os.path.join(screenshot_folder, f"{name}.png"))
Enfin, on dit à notre navigateur de prendre une capture d’écran et de la sauvegarder dans le dossier qu’on vient de préparer, avec le nom qu’on a choisi.
Configurer le navigateur et accéder au jeu de morpion
driver = webdriver.Chrome() driver.get("https://www.google.com/search?q=jeu+morpion+google")
On initialise notre navigateur Chrome et on lui dit d’aller sur la page Google pour chercher le jeu de Morpion.
Accepter les conditions d’utilisation de Google
consent_button = driver.find_element(By.CSS_SELECTOR, "button[id='W0wltc']") consent_button.click()
Ensuite, on trouve le bouton pour accepter les conditions d’utilisation de Google (oui, on est tous un peu flemmards et on ne les lit jamais) et on clique dessus.
Capture d’écran
take_screenshot(driver, "apres_consentement")
Laisser le temps au jeu de se charger
time.sleep(3)
Et on termine avec une petite pause de 3 secondes, le temps que tout se charge correctement et que le jeu soit prêt à être joué.
La boucle infinie
while True:
Ici, on commence par dire à l’ordinateur : « Tant que tu as de l’énergie, continue de jouer ! » C’est une boucle infinie qui ne s’arrêtera que si on décide manuellement de stopper le script.
Parcourir le plateau de jeu
for row in range(3): for col in range(3):
Ensuite, on fait deux boucles pour parcourir toutes les cases du Morpion. La première boucle (avec row
) va de 0 à 2 et représente les lignes, et la deuxième boucle (avec col
) va aussi de 0 à 2 et représente les colonnes.
Tentons de cliquer sur une case
try: cell = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.CSS_SELECTOR, f"td[data-col='{col}'][data-row='{row}']")) ) ActionChains(driver).move_to_element(cell).click().perform() print(f"Clic sur la case ({row}, {col}) : OK \n") time.sleep(1)
Là, ça se corse un peu. On dit au navigateur : « Hé, tu vois cette case du Morpion située à la ligne row
et à la colonne col
? Essaye de cliquer dessus ! » Si la case est prête à être cliquée en moins de 10 secondes, on clique. Puis, on attend une petite seconde avec time.sleep(1)
, histoire de laisser le temps au jeu de se mettre à jour.
Gérer les petits soucis
except ElementClickInterceptedException: print(f"La case ({row}, {col}) a été interceptée par un autre élément, on passe à la suivante.") except TimeoutException: print(f"La case ({row}, {col}) n'était pas cliquable dans le temps imparti.")
Mais parfois, ça ne se passe pas comme prévu. Si un autre élément vient se mettre devant notre case, on l’ignore et on passe à la suivante. Si la case ne devient pas cliquable assez vite, on l’ignore aussi. Dans les deux cas, on affiche un petit message pour savoir ce qu’il s’est passé.
La partie est finie, on recommence !
time.sleep(1) try: replay_button = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.CSS_SELECTOR, "g-raised-button[role='button']")) ) replay_button.click() print("Partie terminée, clic sur Rejouer : OK") except NoSuchElementException: print("Bouton Rejouer non trouvé") except TimeoutException: print("Le bouton Rejouer n'était pas cliquable dans le temps imparti.")
Une fois qu’on a tenté notre chance sur toutes les cases, on attend une seconde, et on cherche le bouton « Rejouer » pour lancer une nouvelle partie. Si le bouton est trouvé et cliquable, on clique. Sinon, on affiche un message d’erreur.
Code source complet du bot qui joue au Morpion Google
# Importer le module os pour interagir avec le système d'exploitation import os # Importer webdriver de selenium pour automatiser les actions dans le navigateur from selenium import webdriver # Importer By pour définir comment sélectionner les éléments dans la page from selenium.webdriver.common.by import By # Importer ActionChains pour réaliser des actions complexes comme le drag and drop from selenium.webdriver.common.action_chains import ActionChains # Importer des exceptions spécifiques pour gérer les erreurs potentielles from selenium.common.exceptions import ElementClickInterceptedException, TimeoutException, NoSuchElementException # Importer WebDriverWait pour attendre qu'un élément soit prêt à être manipulé from selenium.webdriver.support.ui import WebDriverWait # Importer expected_conditions comme EC pour définir des conditions d'attente spécifiques from selenium.webdriver.support import expected_conditions as EC # Importer le module time pour manipuler le temps (pauses, etc.) import time # Définir une fonction pour prendre une capture d'écran et la sauvegarder def take_screenshot(driver, name): # Définir le dossier où sauvegarder les captures d'écran screenshot_folder = "screenshots" # Créer le dossier s'il n'existe pas déjà if not os.path.exists(screenshot_folder): os.makedirs(screenshot_folder) # Prendre la capture d'écran et la sauvegarder dans le dossier défini driver.save_screenshot(os.path.join(screenshot_folder, f"{name}.png")) # Initialiser le navigateur Chrome driver = webdriver.Chrome() # Accéder à la page de recherche Google pour le jeu de morpion driver.get("https://www.google.com/search?q=jeu+morpion+google") # Trouver et cliquer sur le bouton pour accepter les conditions d'utilisation de Google consent_button = driver.find_element(By.CSS_SELECTOR, "button[id='W0wltc']") consent_button.click() take_screenshot(driver, "apres_consentement") # Attendre 3 secondes pour s'assurer que la page ait le temps de se charger complètement time.sleep(3) # Boucle infinie pour jouer indéfiniment while True: # Parcourir chaque ligne de la grille de morpion for row in range(3): # Parcourir chaque colonne de la grille de morpion for col in range(3): # Essayer de cliquer sur chaque cellule de la grille try: # Attendre que la cellule soit cliquable et la stocker dans la variable 'cell' cell = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.CSS_SELECTOR, f"td[data-col='{col}'][data-row='{row}']")) ) # Cliquer sur la cellule ActionChains(driver).move_to_element(cell).click().perform() # Imprimer un message confirmant le clic print(f"Clic sur la case ({row}, {col}) : OK \n") # Attendre 1 seconde avant de continuer time.sleep(1) # Gérer le cas où un élément bloque le clic except ElementClickInterceptedException: # Imprimer un message indiquant que la cellule est bloquée print(f"La case ({row}, {col}) a été interceptée par un autre élément, on passe à la suivante.") # Gérer le cas où la cellule n'est pas cliquable dans le temps imparti except TimeoutException: # Imprimer un message indiquant que la cellule n'est pas cliquable print(f"La case ({row}, {col}) n'était pas cliquable dans le temps imparti.") # Attendre 1 seconde à la fin de chaque partie time.sleep(1) # Essayer de cliquer sur le bouton pour rejouer try: # Attendre que le bouton 'Rejouer' soit cliquable et le stocker dans la variable 'replay_button' replay_button = WebDriverWait(driver, 10).until( EC.element_to_be_clickable((By.CSS_SELECTOR, "g-raised-button[role='button']")) ) # Cliquer sur le bouton 'Rejouer' replay_button.click() # Imprimer un message confirmant le clic sur 'Rejouer' print("Partie terminée, clic sur Rejouer : OK") # Gérer le cas où le bouton 'Rejouer' n'est pas trouvé except NoSuchElementException: # Imprimer un message indiquant que le bouton 'Rejouer' n'est pas trouvé print("Bouton Rejouer non trouvé") # Gérer le cas où le bouton 'Rejouer' n'est pas cliquable dans le temps imparti except TimeoutException: # Imprimer un message indiquant que le bouton 'Rejouer' n'est pas cliquable print("Le bouton Rejouer n'était pas cliquable dans le temps imparti.")
Comment améliorer le bot ?
On a décortiqué chaque ligne, chaque commande, et maintenant, tu dois te sentir un peu comme Neo dans Matrix, voyant le code source de la réalité, non ?
Mais en réalité, notre botQu'est-ce qu'un bot ? Un bot, c'est comme un petit génie du..., il est plutôt comme ça :
il est sympa, il fait le job, mais il pourrait être un peu plus futé. Actuellement, il clique partout, sans réfléchir, comme un gamin hyperactif lâché dans un magasin de bonbons. Et si on le rendait un peu plus stratégique ?
5 étapes pour améliorer le bot pour augmenter les chances de gagner au morpion de Google
1. Stratégie de Jeu : Pour le moment, le botQu'est-ce qu'un bot ? Un bot, c'est comme un petit génie du... joue de manière aléatoire. On pourrait le rendre plus malin en implémentant un algorithme de minimax, typiquement utilisé pour les jeux à deux joueurs comme le morpion. Le minimax permettrait au botQu'est-ce qu'un bot ? Un bot, c'est comme un petit génie du... de calculer le meilleur coup possible à chaque tour. Il existe des tonnes de tutoriels là-dessus, donc si tu as envie de mettre les mains dans le cambouis, fonce !
2. Apprentissage Automatique : Pourquoi pas entraîner un modèle de machine learning pour jouer au morpion ? Des frameworks comme TensorFlow ou PyTorch pourraient t’aider. Attention, ça risque d’être un peu « exagéré » pour un simple jeu de morpion, mais qui sait, tu pourrais créer le prochain AlphaGo du morpion !
3. Interface Utilisateur : Pourquoi ne pas développer une petite interface graphique avec Tkinter ou PyQt pour rendre les interactions avec le botQu'est-ce qu'un bot ? Un bot, c'est comme un petit génie du... plus user-friendly ?
4. Gestion des Erreurs : Notre botQu'est-ce qu'un bot ? Un bot, c'est comme un petit génie du... est plutôt robuste, mais on pourrait toujours améliorer sa gestion des erreurs. Par exemple, ajouter des logs plus détaillés ou des tentatives de récupération en cas d’erreur pourrait être un plus.
5. Optimisation du Code : Enfin, une petite session de refactoring ne fait jamais de mal. Peut-être qu’il y a des parties du code qui pourraient être optimisées ou écrites de manière plus pythonique.
Pour finir, j’espère que t’as kiffé la balade autant que moi, et que t’as réussi à piger deux-trois trucs sur ce petit botQu'est-ce qu'un bot ? Un bot, c'est comme un petit génie du... joueur de morpion. N’hésites pas à l’améliorer et à le partager 😉
Et si tu as vraiment kiffé la création de ce p’tit botQu'est-ce qu'un bot ? Un bot, c'est comme un petit génie du..., hésites pas à jeter un oeil sur le tuto qui te permet de créer un script de surveillance de backlinks.