@@ -7,21 +7,17 @@ import * as cheerio from 'cheerio';
77import Match from '../models/Match.js' ;
88import Standing from '../models/Standing.js' ;
99
10- // 🔹 Constantes
11- const CHAMPIONSHIP_ID = '6985bd859903c98a455ca98d' ; // ton championnat
10+ // 🔹 Club fixe
1211const CLUB_TEAM_NAME = "AS SAINT-BARTHELEMY D'ANJOU V.B." ;
13- const FFVB_URL =
14- 'https://www.ffvbbeach.org/ffvbapp/resu/vbspo_calendrier.php?saison=2025%2F2026&codent=ABCCS&poule=3MB&division=&tour=&calend=COMPLET&x=15&y=15' ;
1512
16- // 🔹 Utilitaire pour parser date FR -> ISO
13+ // 🔹 Utilitaires
1714function parseDateFR ( dateStr , timeStr ) {
1815 const [ day , month , year ] = dateStr . split ( '/' ) . map ( Number ) ;
1916 const fullYear = year < 100 ? 2000 + year : year ;
2017 const [ hours , minutes ] = timeStr . split ( ':' ) . map ( Number ) ;
2118 return new Date ( fullYear , month - 1 , day , hours , minutes ) . toISOString ( ) ;
2219}
2320
24- // 🔹 Transforme string sets en array d'objets pour Mongo
2521function parseSetsDetail ( setsStr ) {
2622 if ( ! setsStr ) return [ ] ;
2723 return setsStr . split ( ',' ) . map ( ( s , idx ) => {
@@ -30,15 +26,19 @@ function parseSetsDetail(setsStr) {
3026 } ) ;
3127}
3228
33- // 🔹 Fonction principale
34- async function scrapeFFVB ( ) {
29+ // 🔹 Scraping d’un championnat
30+ async function scrapeChampionship ( champ ) {
3531 try {
36- console . log ( '📡 Lancement de Puppeteer...' ) ;
32+ console . log ( `\n🏐 ${ champ . name || 'Championnat inconnu' } ` ) ;
33+ console . log ( `🔗 ${ champ . federationUrl } ` ) ;
34+ if ( ! champ . federationUrl ) {
35+ console . warn ( `⚠️ Championnat ${ champ . name || champ . _id } n’a pas d’URL, skipping...` ) ;
36+ return ;
37+ }
38+
3739 const browser = await puppeteer . launch ( { headless : true } ) ;
3840 const page = await browser . newPage ( ) ;
39-
40- console . log ( '📊 Récupération du HTML...' ) ;
41- await page . goto ( FFVB_URL , { waitUntil : 'networkidle2' } ) ;
41+ await page . goto ( champ . federationUrl , { waitUntil : 'networkidle2' } ) ;
4242 const html = await page . content ( ) ;
4343 await browser . close ( ) ;
4444
@@ -55,26 +55,28 @@ async function scrapeFFVB() {
5555 const tds = $ ( tr ) . find ( 'td' ) ;
5656 if ( tds . length < 6 ) return ;
5757
58- const homeTeam = $ ( tds [ 3 ] ) . text ( ) . trim ( ) ;
59- const awayTeam = $ ( tds [ 5 ] ) . text ( ) . trim ( ) ;
58+ const row = [ ] ;
59+ tds . each ( ( j , td ) => row . push ( $ ( td ) . text ( ) . trim ( ) ) ) ;
60+
61+ const homeTeam = row [ 3 ] ;
62+ const awayTeam = row [ 5 ] ;
6063 if ( ! homeTeam || ! awayTeam ) return ;
6164
6265 if ( homeTeam === CLUB_TEAM_NAME || awayTeam === CLUB_TEAM_NAME ) {
6366 const homeAway = homeTeam === CLUB_TEAM_NAME ? 'home' : 'away' ;
64- const scoreFor = homeAway === 'home' ? parseInt ( $ ( tds [ 6 ] ) . text ( ) ) || 0 : parseInt ( $ ( tds [ 7 ] ) . text ( ) ) || 0 ;
65- const scoreAgainst = homeAway === 'home' ? parseInt ( $ ( tds [ 7 ] ) . text ( ) ) || 0 : parseInt ( $ ( tds [ 6 ] ) . text ( ) ) || 0 ;
66- const dateISO = parseDateFR ( $ ( tds [ 1 ] ) . text ( ) . trim ( ) , $ ( tds [ 2 ] ) . text ( ) . trim ( ) ) ;
67- const setsDetail = parseSetsDetail ( $ ( tds [ 8 ] ) . text ( ) . trim ( ) ) ;
67+ const scoreFor = homeAway === 'home' ? parseInt ( row [ 6 ] ) || 0 : parseInt ( row [ 7 ] ) || 0 ;
68+ const scoreAgainst = homeAway === 'home' ? parseInt ( row [ 7 ] ) || 0 : parseInt ( row [ 6 ] ) || 0 ;
69+ const dateISO = parseDateFR ( row [ 1 ] , row [ 2 ] ) ;
70+ const setsDetail = parseSetsDetail ( row [ 8 ] ) ;
6871
69- // 🔹 Déterminer le status correctement
7072 const matchDate = new Date ( dateISO ) ;
7173 let status = 'scheduled' ;
7274 if ( matchDate <= now && ( scoreFor > 0 || scoreAgainst > 0 ) ) {
7375 status = 'played' ;
7476 }
7577
7678 matches . push ( {
77- championshipId : CHAMPIONSHIP_ID ,
79+ championshipId : champ . _id ,
7880 opponentName : homeAway === 'home' ? awayTeam : homeTeam ,
7981 date : dateISO ,
8082 homeAway,
@@ -86,16 +88,16 @@ async function scrapeFFVB() {
8688 }
8789 } ) ;
8890
89- console . log ( '💾 Mise à jour des matchs dans MongoDB...' ) ;
91+ console . log ( `🧪 ${ matches . length } matchs détectés` ) ;
92+
9093 for ( const m of matches ) {
9194 const existing = await Match . findOne ( {
92- championshipId : CHAMPIONSHIP_ID ,
95+ championshipId : champ . _id ,
9396 opponentName : m . opponentName ,
9497 date : m . date ,
9598 } ) ;
9699
97100 if ( existing ) {
98- // 🔹 Vérifier si on a de nouvelles infos avant mise à jour
99101 const needsUpdate =
100102 existing . status !== m . status ||
101103 existing . scoreFor !== m . scoreFor ||
@@ -111,7 +113,6 @@ async function scrapeFFVB() {
111113 console . log ( `➕ Match créé : ${ m . opponentName } (${ m . date } )` ) ;
112114 }
113115 }
114- console . log ( `🎉 ${ matches . length } matchs analysés.` ) ;
115116
116117 // -----------------------------
117118 // 🔹 Scraping des standings
@@ -139,7 +140,7 @@ async function scrapeFFVB() {
139140 const coefficientPoints = parseFloat ( $ ( tds [ 18 ] ) . text ( ) ) || 0 ;
140141
141142 standings . push ( {
142- championshipId : CHAMPIONSHIP_ID ,
143+ championshipId : champ . _id ,
143144 teamName,
144145 rank,
145146 played,
@@ -156,22 +157,27 @@ async function scrapeFFVB() {
156157 } ) ;
157158
158159 console . log ( '💾 Mise à jour des standings dans MongoDB...' ) ;
159- let updatedCount = 0 ;
160160 for ( const s of standings ) {
161- await Standing . findOneAndUpdate ( { championshipId : CHAMPIONSHIP_ID , teamName : s . teamName } , s , { upsert : true } ) ;
162- updatedCount ++ ;
161+ await Standing . findOneAndUpdate ( { championshipId : champ . _id , teamName : s . teamName } , s , { upsert : true } ) ;
163162 }
164-
165- console . log ( `🎉 ${ updatedCount } équipes mises à jour ou créées.` ) ;
163+ console . log ( `🎉 ${ standings . length } équipes mises à jour ou créées` ) ;
166164 } catch ( err ) {
167165 console . error ( '❌ Erreur pendant le scraping :' , err ) ;
168166 }
169167}
170168
171169// -----------------------------
172- // 🔹 Connexion MongoDB via .env
170+ // 🔹 Connexion MongoDB et scraping de tous les championnats
173171// -----------------------------
174172mongoose
175173 . connect ( process . env . MONGO_URI || 'mongodb://127.0.0.1:27017/saintbarthvolley' )
176- . then ( ( ) => scrapeFFVB ( ) )
174+ . then ( async ( ) => {
175+ console . log ( '✅ MongoDB connecté' ) ;
176+ const championships = await mongoose . connection . db . collection ( 'championships' ) . find ( ) . toArray ( ) ;
177+
178+ console . log ( `🚀 ${ championships . length } championnats à scraper` ) ;
179+ for ( const champ of championships ) {
180+ await scrapeChampionship ( champ ) ;
181+ }
182+ } )
177183 . finally ( ( ) => mongoose . disconnect ( ) ) ;
0 commit comments