Ошибка: Ошибка оценки: Ошибка ссылки: страница не определена Кукловод Node.js

#javascript #puppeteer

Вопрос:

Я начинаю заниматься веб-скребком, и я очень новичок в DOM, html и CSS, и я использую Node.js и Кукловод. В консоли Chrome при просмотре выпадающего меню я вижу дерево:

 <select id="variante" class="form-control" name="attribute_variante" data-attribute_name="attribute_variante" data-show_option_none="yes"><option value="">Scegli un'opzione</option><option value="8 Velocità - Work" class="attached enabled">8 Velocità - Work</option><option value="8 Velocità - Family" class="attached enabled">8 Velocità - Family</option><option value="8 Velocità - Child Pack" class="attached enabled">8 Velocità - Child Pack</option></select>

 

который содержит 4 варианта, и для доступа к ним вам нужно нажать на кнопку

 <i class="flaticon-bottom4"></I>
 

и когда выбран один вариант, два других селектора (описание вариации и цена ) получают значения

 <div class="single_variation_wrap"><div class="woocommerce-variation single_variation" style=""><div class="woocommerce-variation-description"><p>Versione con cambio interno al mozzo Shimano Nexus a 8 velocità e Child Pack che comprende: cestone posteriore porta bimbi pieghevole, pedane laterali pieghevoli.</p>
</div><div class="woocommerce-variation-price"><span class="price"><span class="woocommerce-Price-amount amount"><bdi><span class="woocommerce-Price-currencySymbol">€</span>1.990,00</bdi></span></span></div><div class="woocommerce-variation-availability"><p class="stock available-on-backorder">Disponibile su ordinazione</p>
</div> </div><div class="woocommerce-variation-add-to-cart variations_button woocommerce-variation-add-to-cart-enabled"><div class="quantity"> <label class="screen-reader-text" for="quantity_615a86b1a5562">Bicicapace - Justlong quantità</label> <input type="number" id="quantity_615a86b1a5562" class="input-text qty text" step="1" min="1" max="" name="quantity" value="1" title="Qtà" size="4" placeholder="" inputmode="numeric"></div><div id="wc-stripe-payment-request-wrapper" style="clear:both;padding-top:1.5em;display:none;"><div id="wc-stripe-payment-request-button"> <!-- A Stripe Element will be inserted here. --></div></div><p id="wc-stripe-payment-request-button-separator" style="margin-top:1.5em;text-align:center;display:none;">— OPPURE —</p> <button type="submit" class="single_add_to_cart_button button alt">Aggiungi al carrello</button> <input type="hidden" name="add-to-cart" value="19487"> <input type="hidden" name="product_id" value="19487"> <input type="hidden" name="variation_id" class="variation_id" value="21306"></div></div>
 

Я пытаюсь получить значения 4 параметров внутри цикла for с помощью

 var variations = [];


    let loop = document.querySelector('select[class=form-control]').options.length; 
    product['Variations'] = loop ?? 1;
    console.log(loop);

    for (var i = 1; i < loop; i  ) {

      let variationtName = document.querySelector('select[class=form-control]').options[i].value;

      
      let select = await page.waitForSelector('select[class=form-control]'); 


      // let select = document.querySelector('select[class=form-control]');
      await select.select(variationtName);
      let variationDescription = document.querySelector('div[class=woocommerce-variation-description] > p').innerText;
      let variationPrice = document.querySelector('div[class=woocommerce-variation-price]').innerText;


      let variant = {

        'Variation name': variantName ?? 'N/A',
        'Variation price': variationPrice ?? 'N/A',
        'Variation description': variationDescription ?? 'N/A'

      }
      variations.push(variant);

    }
 

Но я получаю ошибку:

 <pre>Error: Evaluation failed: ReferenceError: page is not defined<br> amp;nbsp; amp;nbsp;at __puppeteer_evaluation_script__:33:20<br> amp;nbsp; amp;nbsp;at ExecutionContext._evaluateInternal (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/puppeteer/lib/cjs/puppeteer/common/ExecutionContext.js:221:19)<br> amp;nbsp; amp;nbsp;at runMicrotasks (amp;<anonymousamp;>)<br> amp;nbsp; amp;nbsp;at processTicksAndRejections (node:internal/process/task_queues:94:5)<br> amp;nbsp; amp;nbsp;at async ExecutionContext.evaluate (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/puppeteer/lib/cjs/puppeteer/common/ExecutionContext.js:110:16)<br> amp;nbsp; amp;nbsp;at async exports.ingestInventory (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/api/src/controllers/ingest.controller.js:43:14)</pre>
 

Как перейти page к evaluate функции или мне следует объявить новую страницу в ее теле?

Большое спасибо

Комментарии:

1. Код выполняется в контексте DOM, поэтому page переменная там недопустима. Вам следовало бы позвонить этому за пределами evaluate .

2. Вы действительно используете кукольника? Как возникают document.querySelector и page.waitForSelector появляются в одном и том же контексте.

3. @Эльдар хорошо, я понимаю. Так могу ли я также запустить цикл снаружи evaluate ?

4. @Рикки Мо говорит, что я использую Кукловода, и вы правы, page waitFirSelector вот где я получаю ошибку. Как и предлагалось, я должен запустить цикл снаружи evaluate ..

Ответ №1:

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

 // this returns all the options
const variationNames = await page.evaluate(() =>
  Array.from(document.querySelector('select[class=form-control]').options).map(({
    value
  }) => value)
);

// the select
const select = await page.waitForSelector('select[class=form-control]');
const variations = [];

for (var i = 1; i < variationNames.length; i  ) {
  const variationtName = variationNames[i];
  // wait for selection 
  await select.select(variationtName);
  // evaluate to get the variation info
  const variationInfo = await page.evaluate(() => {
    const variationDescription =
      document.querySelector('div[class=woocommerce-variation-description] > p').innerText;
    const variationPrice = document.querySelector('div[class=woocommerce-variation-price]').innerText;
    const v = {
      price: variationPrice ?? 'N/A',
      description: variationDescription ?? 'N/A'
    }
    return v;
  });
  // populate the array
  variations.push({
    name: variationtName,
    ...variationInfo
  });
} 

Комментарии:

1. Абсолютно! Большое спасибо!! Я вижу, что использовал evaluate неправильно.. На самом деле я вызывал const data = await.page.evaluate(() =>{}); , и внутри тела функции я получал другие данные плюс запускал for цикл ( первая ошибка). Также, конечно, ввод имен вариаций в массив с Array.from().map() помощью возвращает мне массив..( вторая ошибка ). Отдельно для дополнительного ; в => value); нем все работает идеально. Еще раз большое спасибо. Ваше здоровье.