Puppeteer 提供了多种等待机制来处理异步操作和页面加载,确保在执行操作前页面状态已就绪。
1. page.waitForNavigation()
等待页面导航完成,适用于点击链接、提交表单等会触发页面跳转的操作。
javascriptawait Promise.all([ page.waitForNavigation(), page.click('#submit-button') ]);
参数选项:
waitUntil: 'load' | 'domcontentloaded' | 'networkidle0' | 'networkidle2'timeout: 超时时间(毫秒)
2. page.waitForSelector(selector)
等待指定选择器出现在页面中。
javascriptawait page.waitForSelector('.result-item', { visible: true });
参数选项:
visible: 等待元素可见hidden: 等待元素隐藏timeout: 超时时间
3. page.waitForXPath(xpath)
等待 XPath 选择器匹配的元素。
javascriptawait page.waitForXPath('//div[@class="content"]');
4. page.waitForFunction(pageFunction, ...args)
等待自定义函数返回真值,最灵活的等待方式。
javascriptawait page.waitForFunction( () => document.querySelectorAll('.item').length > 5 ); // 带参数 await page.waitForFunction( (count) => document.querySelectorAll('.item').length >= count, {}, 10 );
5. page.waitForTimeout(milliseconds)
等待指定时间(已废弃,建议使用 setTimeout)。
javascript// 旧方法(已废弃) await page.waitForTimeout(1000); // 新方法 await new Promise(resolve => setTimeout(resolve, 1000));
6. page.waitForResponse(urlOrPredicate)
等待特定的网络响应。
javascript// 等待特定 URL 的响应 await page.waitForResponse('https://api.example.com/data'); // 使用谓词函数 await page.waitForResponse(response => response.url().includes('/api/') && response.status() === 200 );
7. page.waitForRequest(urlOrPredicate)
等待特定的网络请求。
javascriptawait page.waitForRequest(request => request.url().includes('/api/data') );
8. page.waitForFrame(frame)
等待指定的 iframe 加载完成。
javascriptconst frame = await page.waitForFrame('iframe-name');
最佳实践:
1. 选择合适的等待方法:
- 导航操作 →
waitForNavigation - 元素操作 →
waitForSelector - 复杂条件 →
waitForFunction - API 调用 →
waitForResponse
2. 设置合理的超时时间:
javascriptawait page.waitForSelector('.element', { timeout: 5000 // 5 秒超时 });
3. 使用 Promise.all 并行等待:
javascriptawait Promise.all([ page.waitForNavigation(), page.click('#link'), page.waitForSelector('.loaded') ]);
4. 处理超时异常:
javascripttry { await page.waitForSelector('.element', { timeout: 3000 }); } catch (error) { console.log('Element not found within timeout'); }
5. 优化等待策略:
javascript// 等待网络空闲(推荐) await page.waitForNavigation({ waitUntil: 'networkidle2' }); // 等待特定元素可见 await page.waitForSelector('.element', { visible: true });
常见问题解决:
问题 1:元素存在但不可见
javascript// 解决方案:等待元素可见 await page.waitForSelector('.element', { visible: true });
问题 2:动态加载内容
javascript// 解决方案:使用 waitForFunction 检查内容 await page.waitForFunction(() => document.querySelectorAll('.item').length > 0 );
问题 3:SPA 路由变化
javascript// 解决方案:等待 URL 变化 await page.waitForFunction(() => window.location.pathname === '/new-page' );