Skip to content

Instantly share code, notes, and snippets.

@borisschapira
Created December 9, 2025 13:36
Show Gist options
  • Select an option

  • Save borisschapira/358f8cea61ee3cafe32206c3f9777f39 to your computer and use it in GitHub Desktop.

Select an option

Save borisschapira/358f8cea61ee3cafe32206c3f9777f39 to your computer and use it in GitHub Desktop.
// Script d'extraction des notes depuis EcoleDirecte
function extractGrades() {
const grades = [];
// Parcourir chaque ligne de matière
document.querySelectorAll('tbody tr').forEach(row => {
// Extraire le nom de la matière
const matiereElement = row.querySelector('.discipline .nommatiere .text-bold');
if (!matiereElement) return;
const matiere = matiereElement.textContent.trim();
// Parcourir chaque note de cette matière
row.querySelectorAll('button.note').forEach(button => {
// Extraire la date depuis le title
const title = button.getAttribute('title');
const dateMatch = title.match(/du\s+(\w+\s+\d+\s+\w+)/);
if (!dateMatch) return;
// Convertir la date au format DD/MM/YYYY
const dateStr = dateMatch[1];
const date = parseFrenchDate(dateStr);
// Extraire les informations depuis le screen-reader
const screenReader = button.querySelector('.screen-reader');
let gradeInfo = null;
if (screenReader && screenReader.textContent.trim()) {
const text = screenReader.textContent.trim();
// Ignorer les notes non significatives
if (text.includes('Non significative')) return;
gradeInfo = parseGradeInfo(text);
} else {
// Si screen-reader est vide, utiliser l'élément .valeur
const valeurElement = button.querySelector('.valeur');
if (valeurElement) {
gradeInfo = parseValeurElement(valeurElement);
}
}
if (gradeInfo) {
grades.push({
date: date,
matiere: matiere,
numerateur: gradeInfo.numerateur,
denominateur: gradeInfo.denominateur,
coefficient: gradeInfo.coefficient
});
}
});
});
return grades;
}
// Fonction pour parser l'élément .valeur
function parseValeurElement(valeurElement) {
const text = valeurElement.textContent.trim();
let numerateur = null;
let denominateur = 20;
let coefficient = 1;
// Extraire le coefficient si présent (dans <sup>)
const coeffElement = valeurElement.querySelector('sup.coef');
if (coeffElement) {
const coeffMatch = coeffElement.textContent.match(/([\d,\.]+)/);
if (coeffMatch) {
coefficient = coeffMatch[1].replace(',', '.');
}
}
// Extraire le dénominateur si présent (dans <sub>)
const subElement = valeurElement.querySelector('sub.quotien');
if (subElement) {
const denomMatch = subElement.textContent.match(/\/([\d,\.]+)/);
if (denomMatch) {
denominateur = denomMatch[1].replace(',', '.');
}
}
// Extraire le numérateur (texte direct, en excluant les sous-éléments)
let numerateurText = '';
valeurElement.childNodes.forEach(node => {
if (node.nodeType === Node.TEXT_NODE) {
numerateurText += node.textContent;
}
});
const numerateurMatch = numerateurText.trim().match(/^([\d,\.]+)/);
if (numerateurMatch) {
numerateur = numerateurMatch[1].replace(',', '.');
}
if (numerateur === null) return null;
return {
numerateur: numerateur,
denominateur: denominateur,
coefficient: coefficient
};
}
// Fonction pour parser la date française
function parseFrenchDate(dateStr) {
const months = {
'janvier': '01', 'février': '02', 'mars': '03', 'avril': '04',
'mai': '05', 'juin': '06', 'juillet': '07', 'août': '08',
'septembre': '09', 'octobre': '10', 'novembre': '11', 'décembre': '12'
};
const days = ['lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi', 'dimanche'];
// Nettoyer le jour de la semaine s'il existe
let cleaned = dateStr.trim();
days.forEach(day => {
if (cleaned.toLowerCase().startsWith(day)) {
cleaned = cleaned.substring(day.length).trim();
}
});
// Parser la date au format "30 septembre" ou "30 septembre 2025"
const parts = cleaned.split(/\s+/);
if (parts.length < 2) return null;
const day = parts[0].padStart(2, '0');
const monthName = parts[1].toLowerCase();
const month = months[monthName];
const year = parts.length >= 3 ? parts[2] : new Date().getFullYear().toString();
if (!month) {
console.warn(`Mois non reconnu: \${monthName}`);
return null;
}
return `${day}/${month}/${year}`;
}
// Fonction pour parser les informations de note depuis screen-reader
function parseGradeInfo(text) {
let numerateur = null;
let denominateur = 20; // Par défaut
let coefficient = 1; // Par défaut
// Pattern pour "X sur Y"
const surMatch = text.match(/([\d,\.]+)\s+sur\s+([\d,\.]+)/);
if (surMatch) {
numerateur = surMatch[1].replace(',', '.');
denominateur = surMatch[2].replace(',', '.');
} else {
// Pattern pour une note simple
const simpleMatch = text.match(/^([\d,\.]+)/);
if (simpleMatch) {
numerateur = simpleMatch[1].replace(',', '.');
}
}
// Pattern pour le coefficient
const coeffMatch = text.match(/coefficientée\s+([\d,\.]+)/);
if (coeffMatch) {
coefficient = coeffMatch[1].replace(',', '.');
}
if (numerateur === null) return null;
return {
numerateur: numerateur,
denominateur: denominateur,
coefficient: coefficient
};
}
// Fonction pour générer le TSV (tab-separated) avec virgules
function generateCSV(grades) {
const headers = ['Date', 'Matière', 'Numérateur', 'Dénominateur', 'Coefficient'];
const rows = grades.map(g => [
g.date,
g.matiere,
g.numerateur.toString().replace('.', ','),
g.denominateur.toString().replace('.', ','),
g.coefficient.toString().replace('.', ',')
]);
const csv = [
headers.join('\t'),
...rows.map(row => row.join('\t'))
].join('\n');
return csv;
}
// Fonction pour télécharger le CSV
function downloadCSV(csv, filename = 'notes.csv') {
const blob = new Blob(['\uFEFF' + csv], { type: 'text/csv;charset=utf-8;' });
const link = document.createElement('a');
const url = URL.createObjectURL(blob);
link.setAttribute('href', url);
link.setAttribute('download', filename);
link.style.visibility = 'hidden';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
// Fonction principale d'export
function exportGrades() {
const grades = extractGrades();
const csv = generateCSV(grades);
const today = new Date().toISOString().split('T')[0];
downloadCSV(csv, `notes_${today}.csv`);
console.log(`Export réussi : ${grades.length} notes exportées`);
return grades;
}
// Exécuter l'export
exportGrades();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment