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
161 lines
4.1 KiB
JavaScript
4 weeks ago
|
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,
|
||
|
}
|
||
|
}
|