Initial commit
This commit is contained in:
18
package.json
Normal file
18
package.json
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"name": "orario-itis-api",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "API per estrarre orari scolastici",
|
||||||
|
"main": "server.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "node scraper_orario.js"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "IlDani - Curry141",
|
||||||
|
"license": "AGPL-3.0",
|
||||||
|
"dependencies": {
|
||||||
|
"express": "^4.18.2",
|
||||||
|
"axios": "^1.6.0",
|
||||||
|
"cheerio": "^1.0.0-rc.12",
|
||||||
|
"cors": "^2.8.5"
|
||||||
|
}
|
||||||
|
}
|
||||||
161
server.js
Normal file
161
server.js
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const axios = require('axios');
|
||||||
|
const cheerio = require('cheerio');
|
||||||
|
const cors = require('cors');
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
const port = 3006;
|
||||||
|
|
||||||
|
app.use(cors());
|
||||||
|
app.use(express.json());
|
||||||
|
|
||||||
|
// Mappa dei giorni della settimana
|
||||||
|
const giorniSettimana = ['Lunedì', 'Martedì', 'Mercoledì', 'Giovedì', 'Venerdì', 'Sabato'];
|
||||||
|
|
||||||
|
app.get('/classe', async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { classe } = req.query;
|
||||||
|
|
||||||
|
if (!classe) {
|
||||||
|
return res.status(400).json({ error: 'Parametro classe mancante' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = `https://webapps.itisravenna.it/Orario/index.php?view=classe&id=${classe}`;
|
||||||
|
|
||||||
|
const response = await axios.get(url, {
|
||||||
|
headers: {
|
||||||
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const $ = cheerio.load(response.data);
|
||||||
|
|
||||||
|
const orario = {
|
||||||
|
classe: classe,
|
||||||
|
giorni: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Inizializza tutti i giorni
|
||||||
|
giorniSettimana.forEach(giorno => {
|
||||||
|
orario.giorni[giorno] = [];
|
||||||
|
});
|
||||||
|
|
||||||
|
// Trova la tabella desktop
|
||||||
|
const table = $('.table_desktop');
|
||||||
|
|
||||||
|
if (table.length === 0) {
|
||||||
|
return res.status(404).json({ error: 'Tabella orario non trovata' });
|
||||||
|
}
|
||||||
|
|
||||||
|
let rigaOraIndex = 0;
|
||||||
|
|
||||||
|
// Processa ogni riga della tabella
|
||||||
|
table.find('tr').each((index, row) => {
|
||||||
|
const $row = $(row);
|
||||||
|
|
||||||
|
// Salta la riga header con i giorni
|
||||||
|
if ($row.hasClass('header') && index === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Salta le righe degli intervalli
|
||||||
|
if ($row.find('.break').length > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Conta le celle nella riga
|
||||||
|
const cellCount = $row.find('td').length;
|
||||||
|
|
||||||
|
// Le righe con 7+ celle contengono l'orario
|
||||||
|
if (cellCount >= 7) {
|
||||||
|
rigaOraIndex++;
|
||||||
|
const oraCorrente = rigaOraIndex;
|
||||||
|
|
||||||
|
// Trova le celle dei giorni
|
||||||
|
const dayCells = $row.find('td.cell.center');
|
||||||
|
|
||||||
|
dayCells.each((cellIndex, cell) => {
|
||||||
|
if (cellIndex >= giorniSettimana.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const giorno = giorniSettimana[cellIndex];
|
||||||
|
const $cell = $(cell);
|
||||||
|
|
||||||
|
// Controlla se la cella è vuota
|
||||||
|
const innerTable = $cell.find('table tbody tr td');
|
||||||
|
|
||||||
|
if (innerTable.length === 0) {
|
||||||
|
// Ora vuota
|
||||||
|
orario.giorni[giorno].push({
|
||||||
|
ora: oraCorrente,
|
||||||
|
materia: null,
|
||||||
|
materiaCompleta: null,
|
||||||
|
docenti: [],
|
||||||
|
laboratori: []
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Estrai materia (una sola per cella)
|
||||||
|
const materiaDiv = innerTable.find('.obj[title]').first();
|
||||||
|
const materiaNome = materiaDiv.text().trim();
|
||||||
|
const materiaCompleta = materiaDiv.attr('title') || materiaNome;
|
||||||
|
|
||||||
|
// Estrai TUTTI i docenti
|
||||||
|
const docenti = [];
|
||||||
|
innerTable.find('.obj a[href*="view=docente"]').each((i, docLink) => {
|
||||||
|
const docente = $(docLink).text().trim();
|
||||||
|
if (docente) {
|
||||||
|
docenti.push(docente);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Estrai TUTTI i laboratori (possono essere multipli!)
|
||||||
|
const laboratori = [];
|
||||||
|
innerTable.find('.obj a[href*="view=aula"]').each((i, labLink) => {
|
||||||
|
const laboratorio = $(labLink).text().trim();
|
||||||
|
if (laboratorio) {
|
||||||
|
laboratori.push(laboratorio);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Aggiungi l'ora al giorno
|
||||||
|
orario.giorni[giorno].push({
|
||||||
|
ora: oraCorrente,
|
||||||
|
materia: materiaNome,
|
||||||
|
materiaCompleta: materiaCompleta,
|
||||||
|
docenti: docenti,
|
||||||
|
laboratori: laboratori // Array invece di singolo valore
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
res.json(orario);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Errore:', error.message);
|
||||||
|
if (error.response) {
|
||||||
|
console.error('Status:', error.response.status);
|
||||||
|
}
|
||||||
|
res.status(500).json({
|
||||||
|
error: 'Errore nel recupero dei dati',
|
||||||
|
dettagli: error.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.get('/test', (req, res) => {
|
||||||
|
res.json({
|
||||||
|
status: 'ok',
|
||||||
|
message: 'Server funzionante',
|
||||||
|
endpoints: ['/classe?classe=CODICE_CLASSE']
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
app.listen(port, () => {
|
||||||
|
console.log(`API attiva su http://localhost:${port}`);
|
||||||
|
console.log(`Test: http://localhost:${port}/test`);
|
||||||
|
console.log(`Esempio: http://localhost:${port}/classe?classe=1A`);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user