# 浏览器渲染模式
## 基础 Worker
typescript
import puppeteer from "@cloudflare/puppeteer";
export default {
async fetch(request, env) {
const browser = await puppeteer.launch(env.MYBROWSER);
try {
const page = await browser.newPage();
await page.goto("https://example.com");
return new Response(await page.content());
} finally {
await browser.close(); // 始终在 finally 中执行
}
}
};
## 会话重用
保持会话存活以提高性能:
typescript
let sessionId = await env.SESSION_KV.get("browser-session");
if (sessionId) {
browser = await puppeteer.connect(env.MYBROWSER, sessionId);
} else {
browser = await puppeteer.launch(env.MYBROWSER, { keep_alive: 600000 });
await env.SESSION_KV.put("browser-session", browser.sessionId(), { expirationTtl: 600 });
}
// 不要关闭浏览器以保持会话存活
## 常见操作
| 任务 | 代码 |
|------|------|
| 截图 | `await page.screenshot({ type: "png", fullPage: true })` |
| PDF | `await page.pdf({ format: "A4", printBackground: true })` |
| 提取数据 | `await page.evaluate(() => document.querySelector('h1').textContent)` |
| 填写表单 | `await page.type('#input', 'value'); await page.click('button')` |
| 等待导航 | `await Promise.all([page.waitForNavigation(), page.click('a')])` |
## 并行抓取
typescript
const pages = await Promise.all(urls.map(() => browser.newPage()));
await Promise.all(pages.map((p, i) => p.goto(urls[i])));
const titles = await Promise.all(pages.map(p => p.title()));
## Playwright 选择器
typescript
import { launch } from "@cloudflare/playwright";
const browser = await launch(env.MYBROWSER);
await page.getByRole("button", { name: "Sign in" }).click();
await page.getByLabel("Email").fill("
[email protected]");
await page.getByTestId("submit-button").click();
## 隐身上下文
无需多个浏览器即可实现隔离会话:
typescript
const ctx1 = await browser.createIncognitoBrowserContext();
const ctx2 = await browser.createIncognitoBrowserContext();
// 每个都有隔离的 cookie/存储
## 配额检查
typescript
const limits = await puppeteer.limits(env.MYBROWSER);
if (limits.remaining < 60000) return new Response("Quota low", { status: 429 });
## 错误处理
typescript
try {
await page.goto(url, { timeout: 30000, waitUntil: "networkidle0" });
} catch (e) {
if (e.message.includes("timeout")) return new Response("Timeout", { status: 504 });
if (e.mes