Le problème : Trop de copier-coller
J’étudiais les maths et je me retrouvais constamment à copier des exercices de Bibmath.net dans des documents LaTeX. Le site a des tonnes d’exercices de qualité avec des solutions, mais le formatage manuel devenait pénible. Copier, coller, corriger le formatage, ajouter les commandes LaTeX, répéter. Il devait y avoir un meilleur moyen.
J’ai donc construit un scraper qui fait tout cela automatiquement. Rien de fantaisiste, juste un script Python qui récupère les exercices et produit des fichiers LaTeX propres prêts pour la compilation.
Scraping du contenu mathématique français
Le premier défi était de comprendre la structure HTML de Bibmath. Chaque page d’exercice a une mise en page spécifique avec des exercices, des indices (“indication”), et des solutions (“corrigé”). Voici ce que fait le scraper :
def fetch_chapitre(page):
headers = {
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)...',
# ... more headers to avoid getting blocked
}
response = requests.get(page, headers=headers)
soup = BeautifulSoup(response.text, 'lxml')
article = soup.find('article', id='contenugauche')
# Extract chapter title and create structure
title = article.find('h1').get_text(strip=True)
chapitre = Chapitre(title, url=response.url)
# Process each section and exercise
for element in article.find_all(recursive=False):
if 'titrepartie' in element.get('class', []):
# New section found
part_title = element.get_text(strip=True)
current_part = Part(part_title)
chapitre.add_part(current_part)
elif 'exo' in element.get('class', []):
# Exercise found - extract all the data
exercise = extract_exercise_data(element)
current_part.add_exercise(exercise)
Conversion des maths HTML vers LaTeX
La partie la plus délicate était de gérer le contenu mathématique. Bibmath utilise un mélange de formatage HTML et de caractères spéciaux qui devaient être convertis en LaTeX approprié :
def parse(content):
soup2 = BeautifulSoup(str(content), 'lxml')
# Remove unwanted tags but keep the content
for tag in soup2.find_all(['span', 'a', 'img']):
tag.extract()
# Handle numbered lists specially
questions = []
ol_list = soup2.find('ol', class_='enumeratechiffre')
if ol_list:
for i, li in enumerate(ol_list.find_all('li'), 1):
if i == 1:
questions.append("\\par") # LaTeX paragraph break
questions.append(f"{i}. {li.get_text().strip()}")
list_text = "\n\n".join(questions)
ol_list.replace_with(list_text)
return soup2.get_text().strip()
Cela gère le cas courant où les exercices ont plusieurs sous-questions dans des listes numérotées. La sortie est propre en LaTeX.
Génération de fichiers LaTeX
Une fois les données d’exercice analysées, générer le LaTeX était simple. J’ai créé un système de modèles avec des fichiers d’en-tête et de pied de page :
class LatexFile:
def generate_latex(self, chapitre):
self.add_header() # Standard LaTeX packages and setup
# Add source attribution
self.add_source(chapitre)
# Generate exercises section
self.add_content(f"\\title{{{chapitre.title}}}")
for part in chapitre.parts:
self.add_content(f"\\section{{{part.title}}}")
for ex in part.exercises:
self.add_exercise(ex)
# Separate sections for hints and solutions
self.add_pagebreak()
for part in chapitre.parts:
for ex in part.exercises:
self.add_indication(ex)
self.add_pagebreak()
for part in chapitre.parts:
for ex in part.exercises:
self.add_answer(ex)
self.add_footer()
self.save()
Chaque exercice est formaté avec des commandes LaTeX personnalisées que j’ai définies dans l’en-tête :
\exercice{12345, name, date, 3, Étude de fonction}
\enonce{12345}{}
Soit f la fonction définie sur R par f(x) = x² + 2x - 3.
1. Montrer que f est continue sur R.
2. Déterminer les limites de f en ±∞.
\finenonce{12345}
\finexercice
Traitement par lots et génération de PDF
Pour gérer plusieurs chapitres, j’ai construit un système de traitement par lots simple. Le script lit les URLs depuis un fichier texte et les traite toutes :
if __name__ == "__main__":
with open('pages.txt', 'r') as f:
for line in f:
page = line.strip()
get_page(page)
L’exécution du scraper ressemble à ceci :
$ python grab.py
Fichier LaTeX généré : dump/Nombres complexes.tex
Fichier LaTeX généré : dump/Polynômes.tex
Fichier LaTeX généré : dump/Fractions rationnelles.tex
Fichier LaTeX généré : dump/Espaces vectoriels.tex
...
Ensuite, un script bash compile tout en PDF :
#!/bin/bash
for tex_file in "dump"/*.tex; do
filename=$(basename "$tex_file")
echo "Processing $filename..."
pdflatex -output-directory="output" "$tex_file"
if [ $? -eq 0 ]; then
echo "Successfully generated PDF for $filename"
else
echo "Error generating PDF for $filename"
fi
done
Sortie console pendant la compilation :
$ ./gen.sh
Traitement de Nombres complexes.tex...
This is pdfTeX, Version 3...
...
Output written on output/Nombres complexes.pdf (47 pages, 892341 bytes).
PDF généré avec succès pour Nombres complexes.tex
Traitement de Polynômes.tex...
...
PDF généré avec succès pour Polynômes.tex
Ce que j’ai obtenu
Le système final me donne des feuilles d’exercices PDF propres organisées par chapitre et sujet. Chaque PDF contient :
- Section exercices : Tous les problèmes clairement formatés avec des étoiles de difficulté
- Section indices : Séparée pour que je puisse d’abord essayer les problèmes
- Section solutions : Solutions complètes détaillées
Les PDF ont l’air professionnels et sont beaucoup plus faciles à imprimer et étudier que le site web. Je peux maintenant récupérer n’importe quel chapitre de Bibmath et avoir une version LaTeX en quelques secondes.
Voici la structure de fichiers typique après avoir tout exécuté :
dump/
Nombres complexes.tex
Polynômes.tex
Espaces vectoriels.tex
...
output/
Nombres complexes.pdf
Polynômes.pdf
Espaces vectoriels.pdf
...
Si vous voulez l’essayer
Le code est du Python simple avec BeautifulSoup et requests. Vous aurez besoin d’un fichier pages.txt
avec les URLs Bibmath (une par ligne), plus des fichiers LaTeX d’en-tête/pied de page pour le style.
C’est spécifiquement construit pour la structure HTML de Bibmath, donc ça ne fonctionnera pas sur d’autres sites sans modification. Mais si vous étudiez les maths françaises et voulez des exercices mieux formatés, ça pourrait vous faire gagner du temps.