Node.js Puppeteer爬虫子链接输出顺序混乱的解决方法问询
问题:如何保证抓取子链接的输出顺序与urls数组顺序一致?
原代码在循环中创建多个并行的异步自执行函数,由于每个页面加载、抓取的耗时不同,先完成的任务会先输出结果,导致最终顺序与urls数组的编写顺序混乱。
修正方案
核心思路是将并行执行的异步操作改为串行执行,同时优化模块引入、浏览器复用和文件写入逻辑:
修正后的代码
const puppeteer = require('puppeteer'); const fs = require("fs/promises"); // 目标URL数组 const urls = [ "link1", "link2", "link3", "link4" ]; // 串行处理每个URL的主函数 async function processUrls() { let browser; try { // 只启动一次浏览器,复用页面提升效率 browser = await puppeteer.launch({ executablePath: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome' }); // 收集所有抓取结果,用于最终写入文件 const allData = []; // 使用for...of循环串行遍历URL for (const url of urls) { const page = await browser.newPage(); try { await page.goto(url, { waitUntil: 'networkidle0' }); // 抓取当前页面的图片src const data = await page.$$eval("img", (imgs) => { return imgs.map(x => x.src); }); // 按顺序输出结果 console.log(`[${url}] 抓取到的图片链接:`, data); allData.push(...data); } catch (err) { console.error(`处理${url}时出错:`, err); } finally { // 关闭当前页面,避免内存占用 await page.close(); } } // 将所有结果一次性写入文件(避免多次覆盖) await fs.writeFile("data.txt", allData.join('\n')); console.log("所有数据已写入data.txt"); } catch (err) { console.error("全局错误:", err); } finally { // 确保浏览器最终关闭 if (browser) await browser.close(); } } // 执行主函数 processUrls();
关键修改点
- 模块移至顶部:避免循环中重复引入
puppeteer和fs模块,符合Node.js最佳实践。 - 串行执行异步操作:用
for...of循环配合await,确保每个URL的抓取任务完成后,再处理下一个,保证输出顺序与urls数组一致。 - 复用浏览器实例:只启动一次浏览器,每次创建新页面,大幅提升执行效率,减少资源消耗。
- 优化文件写入:收集所有结果后一次性写入,避免原代码中每次写入覆盖之前内容的问题。
- 完善错误处理:针对单个URL的错误做捕获,不影响后续任务执行,同时确保页面和浏览器最终关闭。
内容的提问来源于stack exchange,提问作者sk24
相关产品推荐
相关产品推荐

