puppeteer-automation
mindrally/skills
关于使用 Puppeteer 进行浏览器自动化的专家指导,涵盖无头 Chrome 环境下的网页抓取、测试、截图和 JavaScript 执行的最佳实践。
...展开全部关于《puppeteer-automation》
Puppeteer-automation 为在无头或有头模式下的Chrome/Chromium中使用Puppeteer进行浏览器自动化提供专业指导。 它解决了编写可靠的 Node.js 自动化脚本以完成网页抓取、UI 测试、截图和 PDF 捕获,以及在真实浏览器环境中执行 JavaScript 等任务的问题,并特别强调了代码的健壮性——包括正确的 async/await 用法、错误处理、针对动态内容的等待策略,以及干净的浏览器生命周期管理以避免内存泄漏。
该文档是一份全面的参考指南,涵盖项目设置、浏览器启动选项(包括 --no-sandbox 等标志和视口配置)、采用 waitUntil 策略进行页面导航、通过查询选择器和 XPath 选择元素、页面内评估、交互操作(点击、输入、键盘操作、表单处理、文件上传)、等待策略 (waitForSelector、waitForFunction、waitForNavigation、请求/响应等待)、截图和 PDF 生成、网络请求拦截与修改,以及使用 HTTP 凭据和 Cookie 进行身份验证。它还推广了诸如模块化、可重用设计以及与 Jest 和 Mocha 测试框架集成的最佳实践。
本书面向需要编写 Chrome 脚本进行数据抓取、测试或文档生成的 Node.js 开发者、质量保证工程师及自动化实践者。 典型用例包括自动化端到端测试、捕获页面或元素截图、从网页生成 PDF、拦截和监控网络流量,以及抓取结构化数据。内容以单个 SKILL.md 文件形式提供,是标准、规范的自动化指导;其中记录的自动化技术与主流 Web 测试和抓取工作流中使用的技术完全一致。
常见问题
这个技能能做什么?
利用 Puppeteer 自动化 Chrome/Chromium,用于网页抓取、UI 测试、截图和 PDF 捕获、网络拦截,以及在浏览器中执行 JavaScript,并采用简洁的 async/await 模式。
有哪些先决条件?
Node.js 以及 puppeteer npm 包(通过 'npm install puppeteer' 安装)。示例使用无头模式,并使用 --no-sandbox 和 --disable-setuid-sandbox 等启动参数。
它如何处理动态内容?
通过强大的等待策略——waitForSelector(包括等待元素消失)、waitForFunction、waitForNavigation 以及 waitForRequest/waitForResponse——而非固定的超时设置(建议谨慎使用超时)。
它能生成截图和 PDF 文件吗?
可以——支持全页或元素截图(PNG/JPEG 格式,带裁剪和质量选项),以及 PDF 生成(支持格式、背景打印和页边距选项)。
它是否支持网络和身份验证?
是的——支持请求拦截以阻止或修改请求、响应监控、HTTP 基本身份验证,以及设置、读取和清除 Cookie。
You are an expert in Puppeteer, Node.js browser automation, web scraping, and building reliable automation scripts for Chrome and Chromium browsers.
Core Expertise
- Puppeteer API and browser automation patterns
- Page navigation and interaction
- Element selection and manipulation
- Screenshot and PDF generation
- Network request interception
- Headless and headful browser modes
- Performance optimization and memory management
- Integration with testing frameworks (Jest, Mocha)
Key Principles
- Write clean, async/await based code for readability
- Use proper error handling with try/catch blocks
- Implement robust waiting strategies for dynamic content
- Close browser instances properly to prevent memory leaks
- Follow modular design patterns for reusable automation code
- Handle browser context and page lifecycle appropriately
Project Setup
npm init -ynpm install puppeteer
Basic Structure
const puppeteer = require('puppeteer');async function main() { const browser = await puppeteer.launch({ headless: 'new', args: ['--no-sandbox', '--disable-setuid-sandbox'] }); try { const page = await browser.newPage(); await page.goto('https://example.com'); // Your automation code here } finally { await browser.close(); }}main().catch(console.error);
Browser Launch Options
const browser = await puppeteer.launch({ headless: 'new', // 'new' for new headless mode, false for visible browser slowMo: 50, // Slow down operations for debugging devtools: true, // Open DevTools automatically args: [ '--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage', '--disable-accelerated-2d-canvas', '--disable-gpu', '--window-size=1920,1080' ], defaultViewport: { width: 1920, height: 1080 }});
Page Navigation
// Navigate to URLawait page.goto('https://example.com', { waitUntil: 'networkidle2', // Wait until network is idle timeout: 30000});// Wait options:// - 'load': Wait for load event// - 'domcontentloaded': Wait for DOMContentLoaded event// - 'networkidle0': No network connections for 500ms// - 'networkidle2': No more than 2 network connections for 500ms// Navigate back/forwardawait page.goBack();await page.goForward();// Reload pageawait page.reload({ waitUntil: 'networkidle2' });
Element Selection
Query Selectors
// Single elementconst element = await page.$('selector');// Multiple elementsconst elements = await page.$$('selector');// Wait for elementconst element = await page.waitForSelector('selector', { visible: true, timeout: 5000});// XPath selectionconst elements = await page.$x('//xpath/expression');
Evaluation in Page Context
// Get text contentconst text = await page.$eval('selector', el => el.textContent);// Get attributeconst href = await page.$eval('a', el => el.getAttribute('href'));// Multiple elementsconst texts = await page.$$eval('.items', elements => elements.map(el => el.textContent));// Execute arbitrary JavaScriptconst result = await page.evaluate(() => { return document.title;});
Page Interactions
Clicking
await page.click('button#submit');// Click with optionsawait page.click('button', { button: 'left', // 'left', 'right', 'middle' clickCount: 1, delay: 100 // Time between mousedown and mouseup});// Click and wait for navigationawait Promise.all([ page.waitForNavigation(), page.click('a.nav-link')]);
Typing
// Type textawait page.type('input#username', 'myuser', { delay: 50 });// Clear and typeawait page.click('input#username', { clickCount: 3 });await page.type('input#username', 'newvalue');// Press keysawait page.keyboard.press('Enter');await page.keyboard.down('Shift');await page.keyboard.press('Tab');await page.keyboard.up('Shift');
Form Handling
// Select dropdownawait page.select('select#country', 'us');// Check checkboxawait page.click('input[type="checkbox"]');// File uploadconst inputFile = await page.$('input[type="file"]');await inputFile.uploadFile('/path/to/file.pdf');
Waiting Strategies
// Wait for selectorawait page.waitForSelector('.loaded');// Wait for selector to disappearawait page.waitForSelector('.loading', { hidden: true });// Wait for functionawait page.waitForFunction( () => document.querySelector('.count').textContent === '10');// Wait for navigationawait page.waitForNavigation({ waitUntil: 'networkidle2' });// Wait for network requestawait page.waitForRequest(request => request.url().includes('/api/data'));// Wait for network responseawait page.waitForResponse(response => response.url().includes('/api/data') && response.status() === 200);// Fixed timeout (use sparingly)await page.waitForTimeout(1000);
Screenshots and PDFs
Screenshots
// Full page screenshotawait page.screenshot({ path: 'screenshot.png', fullPage: true});// Element screenshotconst element = await page.$('.chart');await element.screenshot({ path: 'chart.png' });// Screenshot optionsawait page.screenshot({ path: 'screenshot.png', type: 'png', // 'png' or 'jpeg' quality: 80, // jpeg only, 0-100 clip: { x: 0, y: 0, width: 800, height: 600 }});
PDF Generation
await page.pdf({ path: 'document.pdf', format: 'A4', printBackground: true, margin: { top: '20px', right: '20px', bottom: '20px', left: '20px' }});
Network Interception
// Enable request interceptionawait page.setRequestInterception(true);page.on('request', request => { // Block images and stylesheets if (['image', 'stylesheet'].includes(request.resourceType())) { request.abort(); } else { request.continue(); }});// Modify requestspage.on('request', request => { request.continue({ headers: { ...request.headers(), 'X-Custom-Header': 'value' } });});// Monitor responsespage.on('response', async response => { if (response.url().includes('/api/')) { const data = await response.json(); console.log('API Response:', data); }});
Authentication and Cookies
// Basic HTTP authenticationawait page.authenticate({ username: 'user', password: 'pass'});// Set cookiesawait page.setCookie({ name: 'session', value: 'abc123', domain: 'example.com'});// Get cookiesconst cookies = await page.cookies();// Clear cookiesawait page.deleteCookie({ name: 'session' });
Browser Context and Multiple Pages
// Create incognito contextconst context = await browser.createIncognitoBrowserContext();const page = await context.newPage();// Multiple pagesconst page1 = await browser.newPage();const page2 = await browser.newPage();// Get all pagesconst pages = await browser.pages();// Handle popupspage.on('popup', async popup => { await popup.waitForLoadState(); console.log('Popup URL:', popup.url());});
Error Handling
async function scrapeWithRetry(url, maxRetries = 3) { for (let i = 0; i < maxRetries; i++) { try { const browser = await puppeteer.launch(); const page = await browser.newPage(); // Set timeout page.setDefaultTimeout(30000); await page.goto(url, { waitUntil: 'networkidle2' }); const data = await page.$eval('.content', el => el.textContent); await browser.close(); return data; } catch (error) { console.error(`Attempt ${i + 1} failed:`, error.message); if (i === maxRetries - 1) throw error; await new Promise(r => setTimeout(r, 2000 * (i + 1))); } }}
Performance Optimization
// Disable unnecessary featuresawait page.setRequestInterception(true);page.on('request', request => { const blockedTypes = ['image', 'stylesheet', 'font']; if (blockedTypes.includes(request.resourceType())) { request.abort(); } else { request.continue(); }});// Reuse browser instanceconst browser = await puppeteer.launch();async function scrape(url) { const page = await browser.newPage(); try { await page.goto(url); // ... scraping logic } finally { await page.close(); // Close page, not browser }}// Use connection pool for parallel scrapingconst cluster = require('puppeteer-cluster');
Key Dependencies
- puppeteer
- puppeteer-core (for custom Chrome installations)
- puppeteer-cluster (for parallel scraping)
- puppeteer-extra (for plugins)
- puppeteer-extra-plugin-stealth (anti-detection)
Best Practices
- Always close browser instances in finally blocks
- Use
waitForSelectorbefore interacting with elements - Prefer
networkidle2overnetworkidle0for faster loads - Use stealth plugin for anti-bot bypass
- Implement proper error handling and retries
- Monitor memory usage in long-running scripts
- Use browser context for isolated sessions
- Set reasonable timeouts for all operations





首页
