并发POST请求下Puppeteer爬虫无法完整获取数据
问题:并发POST请求下Puppeteer爬虫返回不完整结果
我参考教程用Puppeteer构建了全栈网页爬虫项目,后端基于Node.js Express框架,前端通过POST请求触发爬虫任务。但当同时发起2个及以上POST请求时,服务器并发执行任务,无法返回完整的爬取结果。
具体代码
服务器文件index.js的POST方法:
app.post("/data", async (req, res) => { try { console.log("Connected"); const result = await scrapers.scrape(); console.log("data" + result); res.status(200).json(result); } catch (error) { res.status(500).json(error); } });
scrapers.js中的爬虫函数:
async function scrape() { const browser = await puppeteer.launch({ headless: true }); const page = await browser.newPage(); const all_data= []; //traverse through first 4 pages of website for (i = 1; i < 5; i++) { await page.goto( "https://www.examplewebsite.com/page" + i ); const data = await page.evaluate(function () { const events = document.querySelectorAll(".a"); const cur_data= []; for (i = 0; i < events.length; i++) { cur_data.push(events[i].innerText); } return cur_data; }); all_data.push(data); } browser.close(); return all_data; }
操作与结果
- 操作:第一个请求未完成时发送第二个POST请求
- 预期:两次请求均返回完整的爬取数据
- 实际:返回的数据集要么部分完整,要么一个完整另一个为空
问题原因与解决方法
核心问题是循环变量i未使用let/const声明,导致成为全局变量。当多个请求并发执行时,两个请求的循环会共用同一个全局i,互相干扰循环逻辑——比如第一个请求的循环还没跑完,第二个请求的循环修改了i的值,直接破坏了遍历流程。
另外,browser.close()是异步方法,需要加上await确保浏览器关闭后再返回结果,避免资源泄漏或未完成操作就返回数据。
修复后的scrape函数:
async function scrape() { const browser = await puppeteer.launch({ headless: true }); const page = await browser.newPage(); const all_data= []; // 使用let声明i,避免全局污染 for (let i = 1; i < 5; i++) { await page.goto( "https://www.examplewebsite.com/page" + i ); const data = await page.evaluate(function () { const events = document.querySelectorAll(".a"); const cur_data= []; // 同样用let声明内部的i for (let i = 0; i < events.length; i++) { cur_data.push(events[i].innerText); } return cur_data; }); all_data.push(data); } // 等待浏览器关闭完成 await browser.close(); return all_data; }
修改后,每个请求的循环变量都是独立的局部变量,并发执行时不会互相干扰,同时确保浏览器资源正确释放,就能得到预期的完整爬取结果。
内容的提问来源于stack exchange,提问作者QuestionMan
相关产品推荐
相关产品推荐

