Playwright中CDP并发会话执行出现Target Closed错误排查
问题分析与解决方案
你的代码在多站点爬取时出现Target Closed错误,核心原因是负载均衡器的CDP连接分配逻辑或浏览器资源管理存在问题,结合代码细节来看:
资源关闭逻辑的冗余与风险
你在scrape函数中手动关闭了page、context和browser,但实际上调用browser.close()时,Playwright会自动关闭该浏览器实例下所有的上下文和页面,手动关闭page和context属于冗余操作,还可能因异步时序问题导致意外的资源状态异常。负载均衡器的实例分配问题
你的CDP URL指向负载均衡器,但如果负载均衡器没有正确管理远程浏览器实例——比如将后续请求分配给了已被第一个任务关闭的浏览器进程,就会导致新连接的browser实例本身已处于不可用状态,进而在page.goto时触发Target Closed错误。
代码修复建议
简化资源管理逻辑
去掉冗余的page.close()和context.close(),仅保留browser.close(),并通过try/finally确保资源可靠释放:
const scrape = async (browser, site) => { try { const context = await browser.newContext(); const page = await context.newPage(); await page.goto(site, { timeout: 300_000 }); await page.waitForLoadState('load'); // 读取页面文本等操作 } finally { // 关闭浏览器会自动清理所有上下文和页面 await browser.close().catch(err => console.error('浏览器关闭失败:', err)); } } const sites = ['https://google.com', 'https://bing.com']; for (const site of sites) { const browser = await playwright.chromium.connectOverCDP('my url'); // 可选:检查连接状态,排查负载均衡问题 console.log(`已连接到浏览器实例:${browser.isConnected()}`); await scrape(browser, site); }
并发爬取的优化(可选)
如果需要并发执行爬取任务(符合你"并发且隔离"的需求),可以用Promise.all实现:
const sites = ['https://google.com', 'https://bing.com']; await Promise.all(sites.map(async site => { const browser = await playwright.chromium.connectOverCDP('my url'); await scrape(browser, site); }));
负载均衡器配置检查
重点确认以下几点:
- 负载均衡器是否为每个
connectOverCDP请求分配全新的远程浏览器实例,而非复用已关闭的进程; - 当远程浏览器实例被
browser.close()终止后,负载均衡器是否能及时将其从可用池中移除; - CDP连接的超时配置是否合理,避免因连接闲置被提前断开。
内容的提问来源于stack exchange,提问作者xiience
相关产品推荐
相关产品推荐

