Reputation: 80
I tried Googling the answer to this, but only beginner tutorials seem to come up, and the advanced ones only talk about things like taking screenshots and a few other things.
I just want to have Puppeteer expand Wikipedia entries by clicking on them, before taking the screenshot I have it successfully programmed to take now. Is this possible?
Thanks!
Upvotes: 0
Views: 1197
Reputation: 8851
By default the answer to the question would be: you can collect all collapsible heading elements to an array with a simple page.$$
(alias for document.querySelectorAll
in the chrome api), then elementHandle.click
on all of them in a for...of
loop (array.map or forEach are not that suitable to do async clicks!) and finally create a screenshot with fullPage: true
option.
During testing I've found a puppeteer/chromium bug in the last step: fullPage: true
, so it requires another approach to take the full screenshot of the page.
When [fullPage] true, [it] takes a screenshot of the full scrollable page [...] [source]
The full scrollable page's height is defined at navigation in puppeteer, not at the time we create the screenshot, so if we open more collapsed content after the first render: everything that would appear below the line of the original document.body.scrollHeight
will be cut.
As a workaround we can recalculate scrollHeight
(and scrollWidth
) after all content is opened. I experienced some strange cropping if I didn't wait 1-2 seconds after the clicks, so I forced a page.waitFor(1500)
before the recalculation. A page.setViewport
should be applied on the device before the screenshot (page.screenshot
should not have additional options like fullPage
or clip
together with the previous viewport setting!)
const puppeteer = require('puppeteer')
const iPhone = puppeteer.devices['iPhone 6']
async function fn() {
const browser = await puppeteer.launch({ headless: true })
const page = await browser.newPage()
await page.emulate(iPhone)
await page.goto('https://en.m.wikipedia.org/wiki/Story_of_the_Year')
await page.waitForSelector('.collapsible-heading')
// collect all collapsed headings to an array and click all of them
const headingHandles = await page.$$('.collapsible-heading')
for (const el of headingHandles) {
await el.click()
}
// let a bit time for scrollHeight to be finalized
await page.waitFor(1500)
// set viewPort to fullPage manually
const scrollHeight = await page.evaluate(() => document.body.scrollHeight)
const scrollWidth = await page.evaluate(() => document.body.scrollWidth)
await page.setViewport({ width: scrollWidth, height: scrollHeight })
await page.screenshot({ path: 'wiki.png' })
await browser.close()
}
fn()
Upvotes: 2