Created
June 11, 2025 19:11
-
-
Save nichoth/5dce125cb5eca9dde5bd22cdb86033e9 to your computer and use it in GitHub Desktop.
Puppeteer again
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// @ts-check | |
import puppeteer from 'puppeteer' | |
import fs from 'node:fs/promises' | |
import path from 'node:path' | |
import { fileURLToPath } from 'node:url' | |
const __filename = fileURLToPath(import.meta.url) | |
const __dirname = path.dirname(__filename) | |
const URL = 'https://nolaai.webflow.io/' | |
const browser = await puppeteer.launch({ | |
headless: true, | |
defaultViewport: { | |
width: 1920, | |
height: 1080, | |
deviceScaleFactor: 2 // Retina-like quality | |
} | |
}) | |
const page = await browser.newPage() | |
// Navigate to your website | |
await page.goto(URL, { waitUntil: 'networkidle0' }) | |
// webflow badge | |
await page.evaluate(() => { | |
const interval = setInterval(() => { | |
const badge = document.querySelector('.w-webflow-badge') | |
if (badge) badge.remove() | |
}, 100) | |
setTimeout(() => clearInterval(interval), 30000) | |
}) | |
// rm cookie thing | |
await page.click('.fs-cc-banner__button.w-button') | |
// try to wait for the animation | |
await page.evaluate(async () => { | |
await sleep(3000) | |
}) | |
// Calculate total scrollable height | |
const totalScrollHeight = await page.evaluate(() => document.body.scrollHeight) | |
const scrollStep = 5 // pixels per frame | |
let scrollPosition = 0 | |
let frame = 60 // start at frame 60 b/c we have the intro | |
const outputDir = path.join(__dirname, '..', 'screenshots') | |
await fs.mkdir(outputDir, { recursive: true }) | |
await intro() | |
const startTime = Date.now() | |
// Main loop | |
while (scrollPosition < totalScrollHeight) { | |
// Scroll | |
await page.evaluate((scrollY) => { | |
window.scrollTo(0, scrollY) | |
}, scrollPosition) | |
// Save screenshot | |
const filePath = /** @type {(`${string}.png`)} */(path.join( | |
outputDir, | |
`frame_${('' + frame).padStart(4, '0')}.png` | |
)) | |
await page.screenshot({ | |
path: filePath, | |
type: 'png', | |
fullPage: false, | |
omitBackground: false | |
}) | |
scrollPosition += scrollStep | |
frame++ | |
// Try to stay on a ~16.67ms (60fps) interval | |
const elapsed = Date.now() - startTime | |
const targetTime = frame * (1000 / 60) | |
const sleepTime = targetTime - elapsed | |
if (sleepTime > 0) { | |
await new Promise(resolve => setTimeout(resolve, sleepTime)) | |
} | |
} | |
await browser.close() | |
function sleep (ms) { | |
return new Promise((resolve) => { | |
setTimeout(resolve, ms) | |
}) | |
} | |
// take some screenshots before scrolling | |
// Take 60 screenshots, one every 1/60th of a second (for 1 second) | |
async function intro () { | |
for (let frame = 0; frame < 60; frame++) { | |
const filePath = /** @type {(`${string}.png`)} */(path.join( | |
outputDir, | |
`frame_${String(frame).padStart(4, '0')}.png` | |
)) | |
await page.screenshot({ | |
path: filePath, | |
type: 'png', | |
fullPage: false, | |
omitBackground: false | |
}) | |
// Wait for 1/60th of a second | |
if (frame < 59) { | |
await new Promise(resolve => setTimeout(resolve, 1000 / 60)) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment