Afficher la phase de la lune avec Python

Afficher la phase de la lune avec Python

Voilà un petit projet Python qui a pour but d’afficher le croissant de la Lune au jour d’aujourd’hui. Il y a plusieurs manières de le faire et je voulais vous partager mon code. La Lune reste un symbole important pour nous, surtout en ce mois où Haloween bat son plein. Alors pourquoi ne pas s’intéresser à ses différentes phases ?

3 façons de faire…

J’ai visité 3 façons d’atteindre l’objectif d’afficher la phase de la Lune avec Python.

  1. Ou nous procédons par calcul pur et simple pour afficher le résultat
  2. Ou on utilise une bibliothèque adaptée qui fait le calcul à notre place
  3. Ou on se connecte à une API (site en ligne) qui nous donne le résultat que l’on recherche

Pour la proposition 1), autant vous le dire tout de suite, je me suis aidé d’une IA (Mistral) pour me pondre et chercher le calcul approprié. Voilà ce qui est proposé :

import datetime

def method_1(date=None):
    if date is None:
        date = datetime.datetime.utcnow()

    epoch = datetime.datetime(2000, 1, 6, 18, 14, 0)
    synodic_month = 29.530588853
    delta = date - epoch
    days = delta.total_seconds() / 86400.0
    age = days % synodic_month

    if age < 1.84566:
        label, icon = "Nouvelle Lune", "🌑"
    elif age < 5.536:
        label, icon = "Premier Croissant", "🌒"
    elif age < 9.228:
        label, icon = "Premier Quartier", "🌓"
    elif age < 12.920:
        label, icon = "Gibbeuse croissante", "🌔"
    elif age < 16.611:
        label, icon = "Pleine Lune", "🌕"
    elif age < 20.302:
        label, icon = "Gibbeuse décroissante", "🌖"
    elif age < 23.993:
        label, icon = "Dernier Quartier", "🌗"
    elif age < 27.684:
        label, icon = "Dernier Croissant", "🌘"
    else:
        label, icon = "Nouvelle Lune", "🌑"

    return {
        "label": label,
        "icon": icon,
        "day": date.strftime("%d/%m/%Y"),
    }

print(method_1())

Autrement dit, Python a besoin de calculer les phases depuis le 6 janvier 2000 où la NASA a pu calculer très précisément une nouvelle lune. Avec cela, on peut calculer un pourcentage et qui permet de trouver les différentes phases sous conditions. Top !

Deuxième méthode : à l’aide d’une librairie

En fait, c’est exactement la même chose que pour la première proposition. La librairie trouvée se nomme « ephem« , et permet de faire 1 ligne de code en moins ! Je suppose qu’Ephem est utilisé pour plein d’autres éphémérides, mais donc en fait, il fait sûrement la même chose derrière… Je vous laisse tout de même le code proposé, mais vous verrez que la logique reste la même :

import datetime
import ephem

def method_2(date=None):
    if date is None:
        date = datetime.datetime.now(datetime.timezone.utc)

    date_ephem = ephem.Date(date)
    prev_new_moon = ephem.previous_new_moon(date_ephem)
    age_days = float(date_ephem - prev_new_moon)

    if age_days < 1.84566:
        label, icon = "Nouvelle Lune", "🌑"
    elif age_days < 5.536:
        label, icon = "Premier Croissant", "🌒"
    elif age_days < 9.228:
        label, icon = "Premier Quartier", "🌓"
    elif age_days < 12.920:
        label, icon = "Gibbeuse croissante", "🌔"
    elif age_days < 16.611:
        label, icon = "Pleine Lune", "🌕"
    elif age_days < 20.302:
        label, icon = "Gibbeuse décroissante", "🌖"
    elif age_days < 23.993:
        label, icon = "Dernier Quartier", "🌗"
    elif age_days < 27.684:
        label, icon = "Dernier Croissant", "🌘"
    else:
        label, icon = "Nouvelle Lune", "🌑"

    return {
        "label": label,
        "icon": icon,
        "day": date.strftime("%d/%m/%Y"),
    }

print(method_2())

Et enfin, la 3ème possibilité : utilisation de données externes

Ici, nous allons nous connecter à un site web qui a déjà fait le travail à notre place et pomper ce qui nous intéresse. Ce n’est pas la méthode la plus fiable si le site web en question se trompe et ce n’est pas non plus une API, ce qui aurait facilité grandement l’exercice si les données sont bien structurées. Ici, je cherche les informations depuis les classes du site distant. C’était surtout une manière de s’exercer à se connecter avec un site à l’aide de Python (ce qui était en fait mon premier objectif). Vous pouvez le faire via les imports BeautifulSoup (bs4) et Requests (voir ma fonction dans le dossier functions)

import requests
from bs4 import BeautifulSoup
from babel.dates import format_date
from datetime import datetime

def date_format_lunopia(date):
    return format_date(date, format="EEEE d MMMM yyyy", locale="fr_FR")

def method_3():
    from packages.functions import req

    content = req("https://www.lunopia.com/calendrier-lunaire", requests)
    soup = BeautifulSoup(content, "html.parser")
    rows = soup.find_all("tr")

    for row in rows:
        day_cell = row.find("td", class_="table_cal_jour")
        if not day_cell:
            continue

        span = day_cell.find("span", class_="date_long")
        if not span or not span.string:
            continue

        now = datetime.now()
        date = date_format_lunopia(now).lower()
        date_ligne = span.string.lower().strip()

        if date_ligne == date:
            icon = row.find("td", class_="table_cal_lune")
            label = row.find("td", class_="table_cal_phase")

            return {
                "label": label.string.strip(),
                "icon": icon.string.strip(),
                "day": now.strftime("%d/%m/%Y"),
            }
        
print(method_3())

Donc on importe BeautifulSoup qui permet de jouer avec le DOM d’un contenu HTML aspiré via le module « Requests » afin d’aller chercher les infos sur le site distant : https://www.lunopia.com/calendrier-lunaire. Je parcours ensuite le site afin de trouver la date d’aujourd’hui et de récupérer les données qui s’y attachent.

Conclusion

Ces 3 façons de faire fonctionnent et nous donnent la phase de la Lune en ce moment même.
Encore faut-il publier le résultat sur le web, ce qui n’est pas facile avec Python. Moi, j’ai utilisé onrender.com, qui permet de lier mon projet poussé sur Github à un serveur pouvant lire du Python.
Le résultat final se trouve du coup en ligne ici : https://lerotin.onrender.com/

Que peut-on en tirer ? On est à nouveau face à des choix cornéliens auxquels on peut se confronter quand on développe un outil tel que celui-là. Je répondrai que cela dépend des cas. Si comme moi, cela vous fait marrer d’afficher seulement les phases de la Lune, autant rechercher la formule pour le faire et de le coder sous Python. Si vous devez par contre créer toute une application météo, sans doute que d’utiliser une bibliothèque comme ephem serait avantageux pour votre projet dans sa globalité. Enfin, si on vous demande de vous baser sur les données d’un site ou d’une API existante, opté pour la troisième solution. Autrement dit, cela dépendra toujours du contexte, et c’est souvent le cas dans le milieu extensible qu’est le web. Nous aurions pu également choisir un autre langage, le faire avec Javascript et de l’HTML pour publier le projet plus facilement sur la toile. Mais le but était avant tout de s’entraîner avec Python. J’espère que cela vous aura intéressé.

Je vous souhaite une belle soirée au clair de Lune et à très vite !

Sources

Le site distant :
https://www.lunopia.com/calendrier-lunaire

Mon dépôt sur Github :
https://github.com/ProjetsMerlin/Lerotin

Le projet en ligne :
https://lerotin.onrender.com/

lune

Afficher la phase de la lune avec Python

Newsletter

En maintenance ...