Created
December 9, 2025 13:36
-
-
Save borisschapira/358f8cea61ee3cafe32206c3f9777f39 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 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