DevOps

Automatiser un Rapport de Visites par Email avec Python et Cron sur un VPS

Comment analyser les logs Apache avec Python, generer un rapport HTML et l envoyer automatiquement par email chaque semaine via un cron job sur un VPS Linux.

10 Feb 2026 8 min de lecture 60 vues
60

Lectures

8

Minutes

0

Partages

Introduction

Quand on héberge un site web sur un VPS, on a accès à une mine d'informations dans les logs du serveur : qui visite le site, quelles pages sont consultées, combien de bots passent, quels codes HTTP sont retournés... Mais personne n'a envie de se connecter en SSH chaque matin pour lire des fichiers de logs bruts.

Dans cet article, nous allons mettre en place un système automatisé qui :

  • Analyse les logs Apache pour en extraire des statistiques utiles
  • Distingue les visiteurs humains des bots
  • Génère un rapport HTML stylisé (comme un mini dashboard)
  • L'envoie automatiquement par email chaque semaine via un cron job

Le tout avec un seul script Python, sans aucune dépendance externe.

Le Contexte

On part d'un VPS Linux (Ubuntu) hébergeant un site web derrière Apache. La configuration :

  • Serveur : VPS Ubuntu 22.04
  • Serveur web : Apache 2.4 (site statique) + Nginx/Docker (application Laravel)
  • Logs Apache : format Combined Log, écrit dans /var/log/apache2/access.log
  • Email : compte SMTP OVH pour l'envoi

L'objectif : recevoir chaque lundi matin un email récapitulant l'activité de la semaine passée, sans installer de logiciel supplémentaire sur le serveur.

Étape 1 : Comprendre le format des logs Apache

Apache écrit une ligne par requête dans son access log. En format Combined, chaque ligne ressemble à :

192.168.1.42 - - [10/Feb/2026:14:30:17 +0000] "GET /blog HTTP/1.1" 200 11262 "https://monsite.com/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/144.0.0.0"

Voici ce que contient chaque champ :

ChampExempleDescription
IP192.168.1.42Adresse du visiteur
Date[10/Feb/2026:14:30:17]Horodatage de la requête
Méthode + URLGET /blogPage demandée
Code HTTP200Succès, erreur 404, redirection...
Taille11262Octets envoyés
Refererhttps://monsite.com/D'où vient le visiteur
User-AgentMozilla/5.0 ... ChromeNavigateur ou bot

Étape 2 : Parser les logs avec Python

On utilise une regex pour extraire chaque champ. Aucune bibliothèque externe n'est nécessaire : re, collections.Counter et datetime suffisent.

import re
from collections import Counter
from datetime import datetime, timedelta

LOG_FILE = "/var/log/apache2/access.log"

# Regex pour le format Apache Combined
log_pattern = re.compile(
    r'^(\S+) \S+ \S+ \[([^\]]+)\] "(\S+) (\S+) \S+" (\d{3}) (\d+|-) "(.*?)" "(.*?)"'
)

# Ne garder que les 7 derniers jours
seven_days_ago = datetime.now() - timedelta(days=7)

visits_per_day = Counter()
pages = Counter()
ips = Counter()
http_codes = Counter()

with open(LOG_FILE, "r", errors="ignore") as f:
    for line in f:
        match = log_pattern.match(line)
        if not match:
            continue

        ip, date_raw, method, path, code, size, referer, ua = match.groups()

        # Parser la date
        dt = datetime.strptime(date_raw.split()[0], "%d/%b/%Y:%H:%M:%S")
        if dt < seven_days_ago:
            continue

        visits_per_day[dt.strftime("%Y-%m-%d")] += 1
        pages[path] += 1
        ips[ip] += 1
        http_codes[code] += 1

En quelques lignes, on a déjà les visites par jour, les pages les plus vues, les IPs les plus actives et la répartition des codes HTTP.

Étape 3 : Séparer les humains des bots

C'est un point crucial. Sur un site typique, 50 à 70% du trafic provient de bots (crawlers Google, scanners, scripts automatisés). Si on ne filtre pas, les statistiques sont faussées.

BOT_PATTERNS = [
    "bot", "crawler", "spider", "curl", "python", "wget",
    "scrapy", "semrush", "ahrefs", "gptbot",
    "facebookexternalhit", "google-firebase", "mediapartners"
]

def is_bot(user_agent):
    ua_lower = user_agent.lower()
    if ua_lower in ("-", ""):
        return True
    return any(pattern in ua_lower for pattern in BOT_PATTERNS)

# Utilisation dans la boucle de parsing
human_visits = 0
for line in lines:
    # ... parsing ...
    if not is_bot(ua):
        human_visits += 1

Cette approche par mots-clés est simple mais efficace. Les principaux bots sont détectés :

BotSourceRôle
GooglebotGoogleIndexation Google Search
BingbotMicrosoftIndexation Bing
GPTBotOpenAIEntraînement IA
Mediapartners-GoogleGoogleAdSense
curl / Python-urllibScriptsRequêtes automatisées
SemrushBot / AhrefsBotSEO ToolsAnalyse SEO

Étape 4 : Générer un email HTML stylisé

Plutôt qu'un email texte brut illisible, on génère un rapport HTML avec des tableaux, des couleurs et des indicateurs visuels. Python le permet nativement avec email.mime.

from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

bot_pct = round((total - human_visits) / max(total, 1) * 100, 1)

# Construction du HTML avec des stat-boxes
html = "<html><body>"
html += "<h1>Rapport de Visites</h1>"
html += f"<div class='stat-box'>{total:,} requêtes</div>"
html += f"<div class='stat-box'>{human_visits:,} humains</div>"
html += f"<div class='stat-box'>{bot_pct}% bots</div>"
# ... tableaux de stats ...
html += "</body></html>"

msg = MIMEMultipart("alternative")
msg["Subject"] = f"[Rapport] Visites monsite.com - {date}"
msg["From"] = "noreply@monsite.com"
msg["To"] = "admin@monsite.com"
msg.attach(MIMEText(texte_brut, "plain"))
msg.attach(MIMEText(html, "html"))
Astuce : Envoyer à la fois une version texte et une version HTML (via MIMEMultipart("alternative")) garantit que le mail s'affiche correctement partout, même sur les clients mail qui ne supportent pas le HTML.

Étape 5 : Envoyer avec smtplib (SMTP sécurisé)

L'envoi se fait via le module natif smtplib en connexion SSL. Aucune dépendance externe à installer.

import smtplib
import ssl

SMTP_HOST = "ssl0.ovh.net"
SMTP_PORT = 465
SMTP_USER = "noreply@monsite.com"
SMTP_PASS = "VotreMotDePasse"

context = ssl.create_default_context()

with smtplib.SMTP_SSL(SMTP_HOST, SMTP_PORT, context=context) as server:
    server.login(SMTP_USER, SMTP_PASS)
    server.sendmail(SMTP_USER, "admin@monsite.com", msg.as_string())
    print("Rapport envoyé !")

Les fournisseurs courants et leurs paramètres SMTP :

FournisseurHôte SMTPPortSécurité
OVHssl0.ovh.net465SSL
Gmailsmtp.gmail.com587STARTTLS
Outlooksmtp-mail.outlook.com587STARTTLS
Infomaniakmail.infomaniak.com465SSL

Étape 6 : Automatiser avec cron

Le script est prêt, il ne reste qu'à l'exécuter automatiquement. cron est le planificateur de tâches natif de Linux.

# Ouvrir l'éditeur crontab
crontab -e

# Ajouter cette ligne pour un envoi chaque lundi à 8h
0 8 * * 1 /usr/bin/python3 /home/deployer/report_visits.py >> /home/deployer/report.log 2>&1

Comprendre la syntaxe cron

# Format :
# minute  heure  jour_du_mois  mois  jour_semaine  commande

# Exemples :
0 8 * * 1       # Chaque lundi à 8h00
0 */6 * * *     # Toutes les 6 heures
30 9 1 * *      # Le 1er de chaque mois à 9h30
0 8 * * 1-5     # Du lundi au vendredi à 8h

Bonnes pratiques cron

  • Toujours rediriger les sorties vers un fichier log (>> fichier.log 2>&1)
  • Utiliser les chemins absolus (/usr/bin/python3, pas juste python3)
  • Vérifier avec crontab -l que la tâche est bien enregistrée
  • Tester manuellement le script avant de l'automatiser

Étape 7 : Ajouter des alertes intelligentes

Le rapport peut aussi inclure des alertes conditionnelles. Par exemple, surveiller l'espace disque :

import subprocess

result = subprocess.run(["df", "-h", "/"], capture_output=True, text=True)
disk_line = result.stdout.strip().split("\n")[-1].split()
disk_pct = int(disk_line[4].replace("%", ""))

if disk_pct > 90:
    alert = "Disque critique : " + str(disk_pct) + "%"
    # Ajouter l'alerte dans le HTML du rapport

On peut aussi détecter des anomalies :

  • Pic d'erreurs 404 : possible attaque ou liens cassés
  • IP avec un nombre anormal de requêtes : possible bot malveillant ou DDoS
  • Augmentation soudaine du trafic : article viral ou attaque

Résultat : ce que vous recevez

Chaque lundi, un email arrive avec :

  • Indicateurs clés : requêtes totales, visites humaines, pourcentage de bots
  • Visites par jour : tableau des 7 derniers jours
  • Top 10 pages : les pages les plus consultées (hors assets CSS/JS/images)
  • Top 10 IPs : pour identifier les visiteurs réguliers ou les bots agressifs
  • Navigateurs : répartition Chrome, Firefox, Edge, Mobile...
  • Codes HTTP : 200 (succès), 404 (pages introuvables), 301 (redirections)...
  • Alerte disque : avertissement si l'espace est critique

Le tout dans un email HTML propre, lisible directement sur mobile ou desktop.

Aller plus loin

Combiner avec d'autres sources

Ce script peut être étendu pour inclure :

  • Les logs Docker (docker logs) pour une application conteneurisée
  • Les stats Firebase Analytics ou Google Analytics via leurs APIs
  • Le monitoring serveur (RAM, CPU, uptime)

Alternative : GoAccess

GoAccess est un outil dédié à l'analyse de logs en temps réel. Il génère des rapports HTML interactifs. Cependant, notre approche Python a l'avantage d'être :

  • Entièrement personnalisable
  • Sans dépendance à installer
  • Intégrable facilement avec l'envoi d'email

Récapitulatif

ComposantOutilRôle
Parsing des logsPython re + CounterExtraire les statistiques
Détection des botsListe de patterns User-AgentSéparer humains et bots
Génération du rapportPython email.mimeEmail HTML stylisé
EnvoiPython smtplib (SSL)SMTP sécurisé
AutomatisationcronExécution hebdomadaire
AlertesPython subprocessSurveillance disque et anomalies

Conclusion

Avec un seul script Python d'environ 200 lignes et un cron job, on obtient un système de reporting complet qui rivalise avec des outils bien plus complexes. L'avantage majeur : zéro dépendance externe. Tout repose sur la bibliothèque standard de Python et les outils natifs de Linux.

Cette approche est réutilisable sur n'importe quel VPS avec Apache ou Nginx. Il suffit d'adapter le chemin du fichier de log et la regex de parsing si le format diffère.

Conseil : Commencez par lancer le script manuellement pour vérifier que le rapport est correct, puis ajoutez-le à cron une fois validé. Et n'oubliez pas de toujours rediriger les sorties vers un fichier log pour faciliter le débogage en cas de problème.

Tags

VPS Python Cron Analytics

Partagez cet article

Twitter Facebook LinkedIn
JY
Jordane YENO

Developpeur Full Stack passionne par le web et les nouvelles technologies

En savoir plus

Articles similaires