Node.js使用Playwright并行获取多页面内容报错如何解决?
Playwright批量并行获取页面内容报错解决方案
错误根因
- 遍历URL数组时误用
for...in语法:for (url in item.urls)获取的是数组索引(0、1等数字字符串)而非真实URL地址,非法地址导致page.goto执行失败,进入finally块提前关闭实例,触发Target closed报错 - 每次调用
getContent都单独启动、销毁浏览器实例:高并发场景下会占用大量CPU、内存资源,资源不足时会导致浏览器进程意外崩溃,触发报错
优化方案
核心思路是复用浏览器实例 + 上下文隔离请求 + 修复遍历语法,优化后代码如下:
import { firefox, type Browser, type BrowserContext } from 'playwright' // 全局复用单个浏览器实例,仅启动一次 let browser: Browser const initBrowser = async () => { if (!browser) { browser = await firefox.launch({ headless: true }) } return browser } const getContent = async (url: string): Promise<string | null> => { const browser = await initBrowser() // 每个请求使用独立的上下文,完全隔离互不影响 let context: BrowserContext | null = null try { context = await browser.newContext() const page = await context.newPage() await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 15000 // 增加超时时间避免慢加载页面报错 }) return await page.content() } catch (err) { console.error(`获取${url}内容失败:`, err) return null // 单个请求失败不影响整批任务 } finally { // 只关闭当前上下文,不关闭全局浏览器 await context?.close() } } // 批量任务执行 const items = [ { urls: ["https://www.google.com", "https://www.example.com"] // other props }, { urls: ["https://www.google.com", "https://www.example.com"] // other props } ] const result = await Promise.all( items.map(async (item) => { const contents = [] // 修复遍历语法,用for...of获取数组元素 for (const url of item.urls) { contents.push(await getContent(url)) } return contents }) ) // 所有任务执行完成后再关闭浏览器 await browser.close()
高并发场景额外优化
如果单次批量任务超过10个,建议添加并发数限制,避免同时打开过多上下文导致资源不足,可以使用p-limit工具实现:
import pLimit from 'p-limit' // 限制同时最多执行5个getContent请求 const limit = pLimit(5) // 调用时包裹一层limit即可 contents.push(await limit(() => getContent(url)))
内容的提问来源于stack exchange,提问作者chenny
相关产品推荐
相关产品推荐

