Add blog posts, cleanup unused files, update components
- Add 100 blog posts covering AI, development, and tech topics - Add .env.example for environment configuration - Add accessibility and lighthouse audit scripts - Remove obsolete SEO reports and temporary files - Remove dev-dist build artifacts and backup files - Remove unused portrait images (moved/consolidated elsewhere) - Update contact form and component improvements Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,479 @@
|
||||
# Puppeteer: Browser Automation mit Chrome DevTools Protocol
|
||||
|
||||
**Meta-Description:** Puppeteer für Browser Automation. Chrome DevTools Protocol, Headless Mode, Screenshots, PDF Generation und Testing.
|
||||
|
||||
**Keywords:** Puppeteer, Browser Automation, Chrome DevTools Protocol, Headless Chrome, Screenshot, PDF, Web Testing
|
||||
|
||||
---
|
||||
|
||||
## Einführung
|
||||
|
||||
Puppeteer ist die **offizielle Node.js Library von Google** für Chrome/Firefox Automation. Über das Chrome DevTools Protocol (CDP) bietet es direkten Zugang zu Browser-Funktionen, die über normale APIs nicht erreichbar sind.
|
||||
|
||||
---
|
||||
|
||||
## 2026 Updates
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ PUPPETEER 2026 │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Neue Features: │
|
||||
│ ├── WebDriver BiDi Protocol Support │
|
||||
│ ├── Firefox vollständig unterstützt │
|
||||
│ ├── Neuer Headless Mode (schwerer zu detecten) │
|
||||
│ ├── Verbesserte Locator API │
|
||||
│ └── 15-20% weniger Memory Usage │
|
||||
│ │
|
||||
│ DevTools Protocol: │
|
||||
│ ├── Network Interception │
|
||||
│ ├── Performance Metrics │
|
||||
│ ├── Coverage Reports │
|
||||
│ ├── Console Logs │
|
||||
│ └── Security/Certificate Handling │
|
||||
│ │
|
||||
│ Use Cases: │
|
||||
│ ├── Web Scraping │
|
||||
│ ├── Automated Testing │
|
||||
│ ├── PDF Generation │
|
||||
│ ├── Screenshot Services │
|
||||
│ └── Performance Auditing │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Setup
|
||||
|
||||
```bash
|
||||
# Mit Chrome Download
|
||||
npm install puppeteer
|
||||
|
||||
# Ohne Chrome (für eigene Installation)
|
||||
npm install puppeteer-core
|
||||
```
|
||||
|
||||
```typescript
|
||||
// basic.ts
|
||||
import puppeteer from 'puppeteer';
|
||||
|
||||
async function main() {
|
||||
const browser = await puppeteer.launch({
|
||||
headless: true, // 'new' Headless Mode ist default
|
||||
args: [
|
||||
'--no-sandbox',
|
||||
'--disable-setuid-sandbox',
|
||||
'--disable-dev-shm-usage'
|
||||
]
|
||||
});
|
||||
|
||||
const page = await browser.newPage();
|
||||
await page.setViewport({ width: 1920, height: 1080 });
|
||||
|
||||
await page.goto('https://example.com');
|
||||
|
||||
const title = await page.title();
|
||||
console.log('Title:', title);
|
||||
|
||||
await browser.close();
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Screenshots & PDFs
|
||||
|
||||
```typescript
|
||||
// Screenshot
|
||||
async function captureScreenshot(url: string, outputPath: string) {
|
||||
const browser = await puppeteer.launch();
|
||||
const page = await browser.newPage();
|
||||
|
||||
await page.setViewport({ width: 1920, height: 1080 });
|
||||
await page.goto(url, { waitUntil: 'networkidle0' });
|
||||
|
||||
// Full Page Screenshot
|
||||
await page.screenshot({
|
||||
path: outputPath,
|
||||
fullPage: true,
|
||||
type: 'png'
|
||||
});
|
||||
|
||||
// Specific Element
|
||||
const element = await page.$('.hero-section');
|
||||
if (element) {
|
||||
await element.screenshot({ path: 'hero.png' });
|
||||
}
|
||||
|
||||
// Mit Clip (Ausschnitt)
|
||||
await page.screenshot({
|
||||
path: 'clip.png',
|
||||
clip: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
width: 800,
|
||||
height: 600
|
||||
}
|
||||
});
|
||||
|
||||
await browser.close();
|
||||
}
|
||||
|
||||
// PDF Generation
|
||||
async function generatePDF(url: string, outputPath: string) {
|
||||
const browser = await puppeteer.launch();
|
||||
const page = await browser.newPage();
|
||||
|
||||
await page.goto(url, { waitUntil: 'networkidle0' });
|
||||
|
||||
// Print-Styles laden
|
||||
await page.emulateMediaType('print');
|
||||
|
||||
await page.pdf({
|
||||
path: outputPath,
|
||||
format: 'A4',
|
||||
printBackground: true,
|
||||
margin: {
|
||||
top: '20mm',
|
||||
right: '20mm',
|
||||
bottom: '20mm',
|
||||
left: '20mm'
|
||||
},
|
||||
displayHeaderFooter: true,
|
||||
headerTemplate: '<div style="font-size:10px; text-align:center; width:100%;">Header</div>',
|
||||
footerTemplate: '<div style="font-size:10px; text-align:center; width:100%;"><span class="pageNumber"></span>/<span class="totalPages"></span></div>'
|
||||
});
|
||||
|
||||
await browser.close();
|
||||
}
|
||||
|
||||
// Invoice PDF aus HTML
|
||||
async function generateInvoicePDF(html: string): Promise<Buffer> {
|
||||
const browser = await puppeteer.launch();
|
||||
const page = await browser.newPage();
|
||||
|
||||
await page.setContent(html, { waitUntil: 'networkidle0' });
|
||||
|
||||
const pdf = await page.pdf({
|
||||
format: 'A4',
|
||||
printBackground: true
|
||||
});
|
||||
|
||||
await browser.close();
|
||||
return pdf;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Form Handling & Interaction
|
||||
|
||||
```typescript
|
||||
async function fillAndSubmitForm(page: Page) {
|
||||
// Text Input
|
||||
await page.type('#email', 'user@example.com', { delay: 50 });
|
||||
await page.type('#password', 'secretpassword', { delay: 50 });
|
||||
|
||||
// Checkbox
|
||||
await page.click('#terms');
|
||||
|
||||
// Select Dropdown
|
||||
await page.select('#country', 'DE');
|
||||
|
||||
// Radio Button
|
||||
await page.click('input[name="plan"][value="premium"]');
|
||||
|
||||
// File Upload
|
||||
const fileInput = await page.$('input[type="file"]');
|
||||
await fileInput?.uploadFile('./document.pdf');
|
||||
|
||||
// Submit
|
||||
await Promise.all([
|
||||
page.waitForNavigation(),
|
||||
page.click('button[type="submit"]')
|
||||
]);
|
||||
}
|
||||
|
||||
// Keyboard & Mouse
|
||||
async function advancedInteraction(page: Page) {
|
||||
// Keyboard
|
||||
await page.keyboard.press('Tab');
|
||||
await page.keyboard.type('Hello World');
|
||||
await page.keyboard.down('Shift');
|
||||
await page.keyboard.press('ArrowLeft');
|
||||
await page.keyboard.up('Shift');
|
||||
await page.keyboard.press('Backspace');
|
||||
|
||||
// Mouse
|
||||
await page.mouse.move(100, 200);
|
||||
await page.mouse.click(100, 200);
|
||||
await page.mouse.wheel({ deltaY: 500 });
|
||||
|
||||
// Drag & Drop
|
||||
const source = await page.$('#drag-source');
|
||||
const target = await page.$('#drop-target');
|
||||
|
||||
if (source && target) {
|
||||
const sourceBox = await source.boundingBox();
|
||||
const targetBox = await target.boundingBox();
|
||||
|
||||
if (sourceBox && targetBox) {
|
||||
await page.mouse.move(
|
||||
sourceBox.x + sourceBox.width / 2,
|
||||
sourceBox.y + sourceBox.height / 2
|
||||
);
|
||||
await page.mouse.down();
|
||||
await page.mouse.move(
|
||||
targetBox.x + targetBox.width / 2,
|
||||
targetBox.y + targetBox.height / 2
|
||||
);
|
||||
await page.mouse.up();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Network Interception
|
||||
|
||||
```typescript
|
||||
import { Page, HTTPRequest } from 'puppeteer';
|
||||
|
||||
async function interceptNetwork(page: Page) {
|
||||
await page.setRequestInterception(true);
|
||||
|
||||
page.on('request', (request: HTTPRequest) => {
|
||||
const resourceType = request.resourceType();
|
||||
const url = request.url();
|
||||
|
||||
// Block Images, CSS, Fonts
|
||||
if (['image', 'stylesheet', 'font'].includes(resourceType)) {
|
||||
request.abort();
|
||||
return;
|
||||
}
|
||||
|
||||
// Block Tracking
|
||||
if (url.includes('analytics') || url.includes('tracking')) {
|
||||
request.abort();
|
||||
return;
|
||||
}
|
||||
|
||||
// Modify Headers
|
||||
const headers = {
|
||||
...request.headers(),
|
||||
'X-Custom-Header': 'value'
|
||||
};
|
||||
|
||||
request.continue({ headers });
|
||||
});
|
||||
|
||||
// Response Interception
|
||||
page.on('response', async (response) => {
|
||||
if (response.url().includes('/api/')) {
|
||||
try {
|
||||
const json = await response.json();
|
||||
console.log('API Response:', json);
|
||||
} catch {}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Mock API Responses
|
||||
async function mockApi(page: Page) {
|
||||
await page.setRequestInterception(true);
|
||||
|
||||
page.on('request', (request) => {
|
||||
if (request.url().includes('/api/users')) {
|
||||
request.respond({
|
||||
status: 200,
|
||||
contentType: 'application/json',
|
||||
body: JSON.stringify([
|
||||
{ id: 1, name: 'Mock User' }
|
||||
])
|
||||
});
|
||||
} else {
|
||||
request.continue();
|
||||
}
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Chrome DevTools Protocol Direct Access
|
||||
|
||||
```typescript
|
||||
async function cdpAccess(page: Page) {
|
||||
const client = await page.target().createCDPSession();
|
||||
|
||||
// Network Conditions (Throttling)
|
||||
await client.send('Network.emulateNetworkConditions', {
|
||||
offline: false,
|
||||
downloadThroughput: 1.5 * 1024 * 1024 / 8, // 1.5 Mbps
|
||||
uploadThroughput: 750 * 1024 / 8, // 750 Kbps
|
||||
latency: 40 // 40ms
|
||||
});
|
||||
|
||||
// CPU Throttling
|
||||
await client.send('Emulation.setCPUThrottlingRate', { rate: 4 });
|
||||
|
||||
// Performance Metrics
|
||||
await client.send('Performance.enable');
|
||||
const metrics = await client.send('Performance.getMetrics');
|
||||
console.log('Performance Metrics:', metrics);
|
||||
|
||||
// Coverage (CSS/JS Usage)
|
||||
await client.send('CSS.startRuleUsageTracking');
|
||||
// ... navigate and interact
|
||||
const coverage = await client.send('CSS.stopRuleUsageTracking');
|
||||
console.log('CSS Coverage:', coverage);
|
||||
|
||||
// Clear Browser Data
|
||||
await client.send('Network.clearBrowserCache');
|
||||
await client.send('Network.clearBrowserCookies');
|
||||
|
||||
// Console Messages
|
||||
client.on('Runtime.consoleAPICalled', (event) => {
|
||||
console.log('Console:', event.type, event.args);
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Performance Testing
|
||||
|
||||
```typescript
|
||||
async function measurePerformance(url: string) {
|
||||
const browser = await puppeteer.launch();
|
||||
const page = await browser.newPage();
|
||||
|
||||
// Performance Observer
|
||||
await page.evaluateOnNewDocument(() => {
|
||||
window.performanceEntries = [];
|
||||
|
||||
const observer = new PerformanceObserver((list) => {
|
||||
window.performanceEntries.push(...list.getEntries());
|
||||
});
|
||||
|
||||
observer.observe({ entryTypes: ['navigation', 'resource', 'paint', 'largest-contentful-paint'] });
|
||||
});
|
||||
|
||||
await page.goto(url, { waitUntil: 'networkidle0' });
|
||||
|
||||
// Metrics abrufen
|
||||
const metrics = await page.metrics();
|
||||
console.log('Puppeteer Metrics:', {
|
||||
JSHeapUsedSize: metrics.JSHeapUsedSize,
|
||||
LayoutCount: metrics.LayoutCount,
|
||||
RecalcStyleCount: metrics.RecalcStyleCount
|
||||
});
|
||||
|
||||
// Performance Timing
|
||||
const timing = await page.evaluate(() => {
|
||||
const t = performance.timing;
|
||||
return {
|
||||
dns: t.domainLookupEnd - t.domainLookupStart,
|
||||
tcp: t.connectEnd - t.connectStart,
|
||||
ttfb: t.responseStart - t.requestStart,
|
||||
download: t.responseEnd - t.responseStart,
|
||||
domInteractive: t.domInteractive - t.navigationStart,
|
||||
domComplete: t.domComplete - t.navigationStart,
|
||||
load: t.loadEventEnd - t.navigationStart
|
||||
};
|
||||
});
|
||||
|
||||
console.log('Timing:', timing);
|
||||
|
||||
// Core Web Vitals
|
||||
const cwv = await page.evaluate(() => {
|
||||
return (window as any).performanceEntries.filter(
|
||||
e => ['largest-contentful-paint', 'first-input', 'layout-shift'].includes(e.entryType)
|
||||
);
|
||||
});
|
||||
|
||||
await browser.close();
|
||||
return { metrics, timing, cwv };
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Stealth Mode
|
||||
|
||||
```typescript
|
||||
import puppeteer from 'puppeteer-extra';
|
||||
import StealthPlugin from 'puppeteer-extra-plugin-stealth';
|
||||
|
||||
puppeteer.use(StealthPlugin());
|
||||
|
||||
async function stealthBrowse() {
|
||||
const browser = await puppeteer.launch({
|
||||
headless: true,
|
||||
args: [
|
||||
'--disable-blink-features=AutomationControlled',
|
||||
'--no-sandbox'
|
||||
]
|
||||
});
|
||||
|
||||
const page = await browser.newPage();
|
||||
|
||||
// Additional Stealth
|
||||
await page.evaluateOnNewDocument(() => {
|
||||
// Chrome Runtime
|
||||
Object.defineProperty(navigator, 'webdriver', {
|
||||
get: () => false
|
||||
});
|
||||
|
||||
// Permissions
|
||||
const originalQuery = window.navigator.permissions.query;
|
||||
window.navigator.permissions.query = (parameters: any) =>
|
||||
parameters.name === 'notifications'
|
||||
? Promise.resolve({ state: 'denied' } as PermissionStatus)
|
||||
: originalQuery(parameters);
|
||||
|
||||
// Plugins
|
||||
Object.defineProperty(navigator, 'plugins', {
|
||||
get: () => [1, 2, 3, 4, 5]
|
||||
});
|
||||
});
|
||||
|
||||
await page.goto('https://bot.sannysoft.com');
|
||||
await page.screenshot({ path: 'stealth-test.png', fullPage: true });
|
||||
|
||||
await browser.close();
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Fazit
|
||||
|
||||
Puppeteer 2026 bietet:
|
||||
|
||||
1. **CDP Direct Access**: Volle Browser-Kontrolle
|
||||
2. **Multi-Browser**: Chrome + Firefox (WebDriver BiDi)
|
||||
3. **New Headless**: Schwerer zu detecten
|
||||
4. **Performance Tools**: Metrics, Coverage, Auditing
|
||||
|
||||
Ideal für Testing, PDF-Generation und Chrome-spezifische Features.
|
||||
|
||||
---
|
||||
|
||||
## Bildprompts
|
||||
|
||||
1. "Puppet master controlling browser strings, automation concept"
|
||||
2. "Chrome DevTools with code connections, developer tools visualization"
|
||||
3. "PDF documents being generated from web pages, document automation"
|
||||
|
||||
---
|
||||
|
||||
## Quellen
|
||||
|
||||
- [Puppeteer Documentation](https://pptr.dev/)
|
||||
- [Puppeteer GitHub](https://github.com/puppeteer/puppeteer)
|
||||
- [Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/)
|
||||
- [Puppeteer Web Scraping 2026](https://roundproxies.com/blog/puppeteer-web-scraping/)
|
||||
Reference in New Issue
Block a user