Что ж, кажется, ваш код верен, но после каждого щелчка дерево DOM каким-то образом перераспределяется, и следующий элемент в цикле ссылается на тот же первый элемент. Мы можем решить эту проблему следующим образом (измененные строки отмечены комментариями):
'use strict';
const puppeteer = require('puppeteer');
(async function main() {
try {
const browser = await puppeteer.launch({ headless: false });
const [page] = await browser.pages();
await page.goto('https://reslife.ucla.edu/reserve');
const result = await page.evaluate(async () => {
document.querySelector('.reserve-grid .col-md-4 input').click();
await new Promise((resolve) => setTimeout(resolve, 2000));
document.querySelector('.reserve-grid .col-md-6 input').click();
await new Promise((resolve) => setTimeout(resolve, 2000));
const data = [];
const length = document.querySelectorAll('.calendar-available').length; // <-
for (let n = 0; n < length; n++) { // <-
const element = document.querySelectorAll('.calendar-available').item(n); // <-
data_sub = [];
element.click();
await new Promise((resolve) => setTimeout(resolve, 2000));
let columns = document.querySelectorAll('.col-md-6');
for(i = 2; i < columns.length; i++){
let info = columns[i].innerText;
data_sub.push(info);
}
data.push(data_sub);
}
return data;
});
console.log(result);
await browser.close();
} catch (err) {
console.error(err);
}
})();
Альтернативно, мы можем использовать эти строки вместо отмеченных
const labels = [...document.querySelectorAll('.calendar-available')].map(el => el.getAttribute('aria-label')); // <-
for (const label of labels) { // <-
const element = document.querySelector(`.calendar-available[aria-label="${label}"]`); // <-