You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 21:30:58