41

Does anybody know how to get the innerHTML or text of an element? Or even better; how to click an element with a specific innerHTML? This is how it would work with normal JavaScript:

var found = false
$(selector).each(function() {
    if (found) return;
    else if ($(this).text().replace(/[^0-9]/g, '') === '5' {
        $(this).trigger('click');
        found = true
    }
});

Thanks in advance for any help!

Grant Miller
  • 27,532
  • 16
  • 147
  • 165
Noah
  • 661
  • 1
  • 8
  • 17

8 Answers8

48

This is how i get innerHTML:

page.$eval(selector, (element) => {
  return element.innerHTML
})
Ryan
  • 658
  • 6
  • 6
  • I do this and console log element.innerHTML and it prints out Promise { }. Even though elements have been rendered to browser(headless false). Do you have any idea why this might be happening? – Gaurav Fotedar Jul 13 '18 at 18:34
  • Please try this as well `await page.goto('https://example.com'); const textContent = await page.evaluate(() => document.querySelector('p').textContent); const innerText = await page.evaluate(() => document.querySelector('p').innerText); console.log(textContent); console.log(innerText);` – Vaishnavi Patel Apr 03 '19 at 07:06
33

Returning innerHTML of an Element

You can use the following methods to return the innerHTML of an element:

page.$eval()

const inner_html = await page.$eval('#example', element => element.innerHTML);

page.evaluate()

const inner_html = await page.evaluate(() => document.querySelector('#example').innerHTML);

page.$() / elementHandle.getProperty() / jsHandle.jsonValue()

const element = await page.$('#example');
const element_property = await element.getProperty('innerHTML');
const inner_html = await element_property.jsonValue();

Clicking an Element with Specific innerHTML

You can use the following methods to click on an element based on the innerHTML that is contained within the element:

page.$$eval()

await page.$$eval('.example', elements => {
  const element = elements.find(element => element.innerHTML === '<h1>Hello, world!</h1>');
  element.click();
});

page.evaluate()

await page.evaluate(() => {
  const elements = [...document.querySelectorAll('.example')];
  const element = elements.find(element => element.innerHTML === '<h1>Hello, world!</h1>');
  element.click();
});

page.evaluateHandle() / elementHandle.click()

const element = await page.evaluateHandle(() => {
  const elements = [...document.querySelectorAll('.example')];
  const element = elements.find(element => element.innerHTML === '<h1>Hello, world!</h1>');
  return element;
});

await element.click();
Grant Miller
  • 27,532
  • 16
  • 147
  • 165
12

This should work with puppeteer:)

const page = await browser.newPage();
const title = await page.evaluate(el => el.innerHTML, await page.$('h1'));
George G
  • 7,443
  • 12
  • 45
  • 59
E. Fortes
  • 1,338
  • 12
  • 12
6

You can leverage the page.$$(selector) to get all your target elments and then use page.evaluate() to get the content(innerHTML), then apply your criteria. It should look something like:

const targetEls = await page.$$('yourFancySelector');
for(let target of targetEls){
  const iHtml = await page.evaluate(el => el.innerHTML, target); 
  if (iHtml.replace(/[^0-9]/g, '') === '5') {
    await target.click();
    break;
  }
}
LeOn - Han Li
  • 9,388
  • 1
  • 65
  • 59
4

I can never get the .innerHtml to work reliable. I always do the following:

let els = page.$$('selector');
for (let el of els) {
  let content = await (await el.getProperty('textContent')).jsonValue();
}

Then you have your text in the 'content' variable.

JMDE
  • 1,085
  • 11
  • 14
3

With regard to this part of your question...

"Or even better; how to click an element with a specific innerHTML."

There are some particulars around innerHTML, innerText, and textContent that might give you grief. Which you can work-around using a sufficiently loose XPath query with Puppeteer v1.1.1.

Something like this:

const el = await page.$x('//*[text()[contains(., "search-text-here")]]');
await el[0].click({     
                button: 'left',
                clickCount: 1,
                delay: 50
            });

Just keep in mind that you will get an array of ElementHandles back from that query. So... the particular item you are looking for might not be at [0] if your text isn't unique.

Options passed to .click() aren't necessary if all you need is a single left-click.

rwinscot
  • 586
  • 6
  • 7
0

You can simply write as below. (no need await sentence in the last part)

const center = await page.$eval('h2.font-34.uppercase > strong', e => e.innerHTML);
Subodh Ghulaxe
  • 18,333
  • 14
  • 83
  • 102
Naga
  • 10,944
  • 2
  • 21
  • 38
-15
<div id="innerHTML">Hello</div>


var myInnerHtml = document.getElementById("innerHTML").innerHTML;
console.log(myInnerHtml);
Liam
  • 27,717
  • 28
  • 128
  • 190