Arsenio Aguirre
Arsenio Aguirre

Reputation: 183

Puppeteer - How to use page.click() inside page.evaluate()

I am scraping a table and each row has a button to show a modal with information. I need to scraping the information from the modal for each row but I dont know how to open the modal. I have tried with page.click(selector) inside page.evaluate() but It didnt work.

I have tested the next code.

const users = await page.evaluate(() => {
  const usersTable = Array.from(document.querySelectorAll('table#grilla > tbody > tr'))
  const userInfo = usersTable.map(async userTable => {
    await page.click('td > a#modificar-2')
    await page.click('div > button[type=submit].close')
    const username = userTable.children[2].innerText
    const firstName = userTable.children[4].innerText
    const lastName = userTable.children[5].innerText
    const email = userTable.children[6].innerText
    const estado = userTable.children[7].innerText
    const fullName = firstName + lastName
    return { username, fullName, email, estado }
  })
  return userInfo
})

I dont know how to pass page.click() or another option inside page.evaluate()

Upvotes: 5

Views: 14058

Answers (3)

You can return css selectors of elements you want to click from page.evaluate and then perform page.click on them. For getting css selector for the element you can use the code from an answer to this question:

const elemToClick = page.evaluate(() => {
  let elem;

  //...

  return cssPath(elem);

  function cssPath(el) {
    if (!(el instanceof Element)) return;
    var path = [];
    while (el.nodeType === Node.ELEMENT_NODE) {
      var selector = el.nodeName.toLowerCase();
      if (el.id) {
        selector += '#' + el.id;
        path.unshift(selector);
        break;
      } else {
        var sib = el,
          nth = 1;
        while ((sib = sib.previousElementSibling)) {
          if (sib.nodeName.toLowerCase() == selector) nth++;
        }
        if (nth != 1) selector += ':nth-of-type(' + nth + ')';
      }
      path.unshift(selector);
      el = el.parentNode;
    }
    return path.join(' > ');
  }
});

page.click(elemToClick);

Upvotes: 0

Kodziak
Kodziak

Reputation: 151

If you use page.evaluate() you're switching the context from node puppeteer to browser, so you have to use JS native functions like click: document.querySelector(selector).click().

If you have errors like Error: Evaluation failed: TypeError: Cannot read property 'click' of null probably the element you wanted to click isn't on the page (or it's hidden or something).

Upvotes: 3

pguardiario
pguardiario

Reputation: 55002

From inside that loop you would do:

userTable.querySelector('td > a#modificar-2').click()

(no await)

Upvotes: 1

Related Questions