как получить все внутренние HTML, когда только $ eval дает результаты ($$ возвращает undefined) - PullRequest
2 голосов
/ 10 июля 2020

Есть таблица, в которой я пытаюсь вытащить 3 информации из каждой строки. После этого он прокручивает страницу вниз, щелкает «загрузить еще», а затем очищает новые данные и так далее, и так далее, пока больше не будет кнопки «загрузить еще».

Чтобы вытащить все данные из таблицы я использовал $$ eval, но это приводит к неопределенному. Однако я получаю данные, если вместо этого использую $ eval, но он извлекает данные только из первой строки таблицы. Почему $$ eval возвращает "undefined" и если я не могу его использовать, как я могу пройти oop через таблицу, чтобы получить все значения с помощью $ eval?

    const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({ headless: false }); // default is true
  const page = await browser.newPage();
  await page.goto('someexamplesite.com', {
    waitUntil: 'domcontentloaded',
  });

  const ExerciseName = await page.$$eval(
    '.ExCategory-results > .ExResult-row:nth-child(2) > .ExResult-cell > .ExHeading > a',
    (e) => e.innerText
  );

  const muscleTargeted = await page.$$eval(
    ' .ExCategory-results > .ExResult-row:nth-child(2) > .ExResult-cell > .ExResult-muscleTargeted > a',
    (e) => e.innerText
  );

  const equipmentType = await page.$$eval(
    '.ExCategory-results > .ExResult-row:nth-child(2) > .ExResult-cell > .ExResult-equipmentType > a',
    (e) => e.innerText
  );

  //click on load more
  await page.waitForSelector(
    '#js-ex-content > #js-ex-category-body > .ExCategory-results > .ExLoadMore > .bb-flat-btn'
  );

  console.log({ ExerciseName, muscleTargeted, equipmentType });

    await browser.close();
})().catch((e) => {
  console.error(e);
});

код, который я пытаюсь очистить

image

1 Ответ

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

Метод page.$$eval запускает Array.from(document.querySelectorAll(selector)) в фоновом режиме, поэтому вы получаете массив. Вы не можете применить (e) => e.innerText к массиву напрямую (даже если он имеет длину 1), не повторяя его или не получая правильные элементы по их правильным индексам (например: e[0].innerText), иначе вы получите undefined.

Вы можете использовать Array.map для перебора совпадающих элементов и сбора innerText каждого в массив.

const exerciseName = await page.$$eval(
    '.ExCategory-results > .ExResult-row:nth-child(2) > .ExResult-cell > .ExHeading > a',
    elements => elements.map(el => el.innerText)
  )

Вывод:

[ 'Rickshaw Carry' ]

Изменить:

Вы можете перебирать классы строк, используя al oop с индексом (проще всего использовать обычный for l oop ) путем (1) подсчета элементов с одинаковыми именами классов:

const rowsCounts = await page.$$eval('.ExCategory-results > .ExResult-row', rows => rows.length)

Затем (2) перебираем дочерние элементы .ExResult-row:nth-child(n) ... и собираем innerText s в массив (exerciseNames) :

const exerciseNames = []
for (let i = 1; i < rowsCounts + 1; i++) { // you mignt need i = 2
  const exerciseName = await page.$eval(
    `.ExCategory-results > .ExResult-row:nth-child(${i}) > .ExResult-cell > .ExHeading > a`,
    el => el.innerText)
  exerciseNames.push(exerciseName)
}

Вывод:

[
  'Rickshaw Carry',
  'Single-Leg Press',
  'Landmine twist',
  'Weighted pull-up',
  'T-Bar Row with Handle',
  'Palms-down wrist curl over bench'
]

Примечание: l oop следует начинать с формы 1, а не 0 в таких случаях, поскольку нет «nth-child (0)». В вашем примере 1-й также отсутствует, поэтому вам может потребоваться начать итерацию с 2.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...