JavaScript - заполнить конструктор объекта из нескольких массивов - PullRequest
2 голосов
/ 09 июля 2020

Я собираю несколько свойств innerText с веб-сайта, который повторяет элементы на своей странице (24 профиля университета с именем, средним рейтингом, количеством программ и т. Д.).

Я тестировал свою маленькую программу с один университет использовал querySelector() для сбора 4-5 внутренних текстов, которые я хотел, объединил их с помощью var u = await Promise.allSettled([arr1, arr2, arr3, arr4, arr5]) и использовал конструктор, который я определил вверху var currUniv = new University(...myArrayOfFacts). Пока все хорошо (по крайней мере, результат ...)

Поскольку страница предлагает 24 предмета университетов одновременно / на одной странице (и все в одной структуре), теперь я хочу использовать querySelectorAll() для возьмите 5 массивов по 24 элемента в каждом go. Если я буду придерживаться var u = await Promise.allSettled([arr1, arr2, arr3, arr4, arr5]), я получу массив из 5 массивов и теперь не знаю (и не могу найти способ успешно погуглить), как я скармливаю по одному элементу каждого массива за раз в свой конструктор.

Следует ли мне вообще избегать размещения всего в одном большом массиве? Я делаю это, потому что думаю, что мне нужно дождаться разрешения всех обещаний ... Или в какой момент мне следует начать цикл по массивам?

Все асинхронно c. Я немного укорачиваю код: и, как я писал далее, это отлично сработало для одного набора DOM-элементов / для одного университета.

Большое спасибо за любые советы, указывающие мне в правильном направлении!

const puppeteer = require('./node_modules/puppeteer');

const startUrl = "https://www.studycheck.de/hochschulen/";

//constructor - shortend
function HSMain(name, ...){
      this.nameHS = name;
      this...
}

const hsfPageVisits = async () => {

  try{
    const browser = await puppeteer.launch({headless: true});
    const page = await browser.newPage();
    await page.goto(startUrl, {waitUntil: 'domcontentloaded'});

   // get first element (name)
      var nameHS = await page.evaluate(() => {
        let name = Array.from(document.querySelectorAll('div .title a')).map(node => node.innerText);
        return name;
      });
   // get second element (rating)
      var rating = await page.evaluate(() => {
        let rate = Array.from(document.querySelectorAll('div .rating-container > div .rating-value')).map(node => node.innerText.trim());
      return rate;
      });
[...more DOM - elements...]

// wait for all promises to resolve
var univArr = await Promise.allSettled([nameHS, rating, ..., ..., ...]);

// spread the array into the object constructor
var myObj = await new HSMain(...univArr);

  await browser.close();
  }
  catch(e){
    console.log("error", e);
  }
};
hsfPageVisits();

1 Ответ

1 голос
/ 09 июля 2020

Итак, у вас есть массив имен, еще один для рейтингов и так далее. Каждый индекс этих массивов соответствует одному и тому же университету, поэтому просто map один из этих массивов и используйте индекс, предоставленный map, чтобы получить значение из остальных массивов, к сожалению, вы не можете использовать здесь синтаксис распространения :

let universities = nameHS.map((name, i) =>
    new University(name, rating[i], theNextArray[i], theArrayAfterThat[i], ...)
);

Мой подход состоял бы в том, чтобы получить все «факты» сразу для каждого университета, а не отдельно в разных массивах. Факты каждого университета сгруппированы в объект или массив, что значительно сократит код, например:

try {
    const browser = await puppeteer.launch({ headless: true });
    const page = await browser.newPage();
    await page.goto(startUrl, { waitUntil: 'domcontentloaded' });

    var universitiesFacts = await page.evaluate(() => {
        let universities = Array.from(document.querySelectorAll(".institute-item")); // first get all university (each university info is contained in an element with a class 'institute-item')
        
        return universities.map(university => [                                      // for each .institute-item element
            university.querySelector(".title a").textContent.trim(),                 // get the name (using querySelector on the .institute-item element)
            university.querySelector(".rating-value").textContent.trim(),            // get the rating
            // ... the rest of facts for the current university
        ]);
    });

    let universities = universitiesFacts.map(facts => new University(...facts));     // now we can use the spread syntax
  
    await browser.close();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...