puppeteer-automation
mindrally/skills
關於使用 Puppeteer 進行瀏覽器自動化的專家指南,內容涵蓋無頭 Chrome 環境中網頁爬取、測試、螢幕截圖及 JavaScript 執行的最佳實務。
...展開全部關於《puppeteer-automation》
Puppeteer-automation 提供關於在無頭(headless)或有頭(headful)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 檔案形式提供標準且正統的自動化指引;其中記載的自動化技術,正是主流網頁測試與資料擷取工作流程中普遍採用的技術。
常見問題
這個技能能做什麼?
利用 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
安裝 puppeteer-automation
請下載並將技能檔案解壓縮至您的 .claude/skills/ 目錄中。
下載 ZIP複製儲存庫並將技能檔案複製到您的專案中。
git clone https://github.com/Mindrally/skills/blob/main/puppeteer-automation/SKILL.md # Copy SKILL.md to your .claude/skills/ directory
複製





首頁
