You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

161 lines
4.1 KiB
JavaScript

const FORMAT = {
hourly: {
temperature: {
type: 'number',
unit: '°C',
},
precipitationProbability: {
type: 'number',
unit: '%',
},
// weatherCode: {
// type: 'number',
// unit: 'Aeronautica Militare Weather Icons',
// },
},
daily: {
minimumTemperature: {
type: 'number',
unit: '°C',
},
maximumTemperature: {
type: 'number',
unit: '°C',
},
// weatherCode: {
// type: 'number',
// unit: 'Aeronautica Militare Weather Icons',
// },
},
}
const range = (start, end) => {
/// returns [start .. (end-1)]
return [...Array(end - start).keys()].map(x => x + start)
}
const parseTemp = el => {
// return el.textContent
return parseFloat(el.textContent)
}
const parsePrecProb = el => {
const text = el.textContent.trim()
return parseFloat(text)
return text
if (text === 'assenti') return 0
if (text === 'deboli') return 0.05
try {
//TODO not 100% sure that this would work as it was never tested
} catch (error) {
console.log(error)
return text
}
}
export default async browser => {
const page = await browser.newPage()
await page.goto('https://www.meteoam.it/it/meteo-citta/pisa')
const meteogramInfoContainer = await page
.locator('.meteogram-info-container')
.waitHandle()
const startTime = new Date().getHours() + 1
const endTime = 24
const scrapeColumn = async i => {
const column = await meteogramInfoContainer.$(
`#weather_info_container_${i}`,
)
const tempDiv = await column.$('.weather-info-temperature')
const precProbDiv = await column.$('.weather-rain-probability')
const temperature = await tempDiv.evaluate(parseTemp)
const precipitationProbability =
await precProbDiv.evaluate(parsePrecProb)
return { temperature, precipitationProbability }
}
const scrapeBlock = async i => {
const block = await meteogramInfoContainer.$(
`.swiper-slide[aria-label="${i + 1} / 5"]`,
)
const tempMaxDiv = await block.$('.meteogram-info-temp-max')
const tempMinDiv = await block.$('.meteogram-info-temp-min')
const maximumTemperature = await tempMaxDiv.evaluate(parseTemp)
const minimumTemperature = await tempMinDiv.evaluate(parseTemp)
return { minimumTemperature, maximumTemperature }
}
const scrapeToday = async () => {
let today = {}
const indices = range(startTime, endTime)
const results = await Promise.all(indices.map(scrapeColumn))
for (let i = startTime; i < endTime; i++) {
today[i] = results[i - startTime]
}
return today
}
const scrapeTomorrow = async () => {
let tomorrow = {}
const indices = range(24 - startTime, 48 - startTime)
const results = await Promise.all(indices.map(scrapeColumn))
for (let i = 0; i < 24; i++) {
tomorrow[i] = results[i]
}
return tomorrow
}
const scrapeDayAfterTomorrow = async () => {
let dayAfterTomorrow = {}
const indices = range(48 - startTime, 72 - startTime)
const results = await Promise.all(indices.map(scrapeColumn))
for (let i = 0; i < 24; i++) {
dayAfterTomorrow[i] = results[i]
}
return dayAfterTomorrow
}
const scrapeWeek = async () => {
let week = {}
const indices = range(0, 5)
const results = await Promise.all(indices.map(scrapeBlock))
for (let i = 0; i < 5; i++) {
week[i] = results[i]
}
return week
}
const [today, tomorrow, dayAfterTomorrow, week] = await Promise.all([
scrapeToday(),
scrapeTomorrow(),
scrapeDayAfterTomorrow(),
scrapeWeek(),
])
await page.close()
return {
format: FORMAT,
today,
tomorrow,
dayAfterTomorrow,
week,
}
}