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

使用Puppeteer爬取网站返回空数组问题求助

问题分析与修复方案

你的代码返回空数组的核心原因是依赖固定nth-child索引定位元素,但移除广告后DOM结构发生偏移,导致后续元素无法被正确匹配,同时还有多处细节问题阻碍数据收集:

具体问题点

  • 广告移除后索引偏移:删除第22、43位元素后,后续元素的索引会自动前移,原循环i从3到53的固定索引逻辑会跳过大量有效元素,甚至触发waitForSelector超时。
  • 无效重复判断:两次重复检查div:nth-child(22)是否存在,且广告移除后该元素已不存在,直接导致循环跳过数据收集逻辑。
  • 弹窗点击无容错:部分页面可能没有弹出广告,直接执行page.click会抛出错误,中断整个爬取流程。
  • 固定延时不可靠:waitForTimeout(3000)无法保证页面完全加载,容易出现元素未渲染完成就执行后续操作的情况。
  • 低效的元素遍历:通过循环索引定位元素的方式极易受DOM结构变化影响,稳定性极差。

修复后的代码

const puppeteer = require("puppeteer");
const express = require("express");
const cors = require("cors");
const app = express();
app.use(cors());
let data = [];

(async () => {
  const browser = await puppeteer.launch({
    headless: false,
    defaultViewport: null,
  });
  const page = await browser.newPage();

  // 弹窗关闭容错逻辑:先判断存在再操作
  const closePopup = async () => {
    const popupBtn = await page.$("#promotionalPopup button");
    if (popupBtn) {
      await popupBtn.click();
      await page.waitForTimeout(500);
    }
  };

  for (let pageNumber = 1; pageNumber < 42; pageNumber++) {
    try {
      await page.goto(`https://naamhinaam.com/baby-girl-names-a?page=${pageNumber}`, {
        waitUntil: "networkidle2" // 等待网络空闲,确保页面加载完成
      });

      await closePopup();

      // 移除广告元素:先判断存在再删除,避免报错
      const ad1 = await page.$("div.name-suggestion.mt-1 > div > div:nth-child(22)");
      if (ad1) await page.evaluate(el => el.remove(), ad1);
      
      const ad2 = await page.$("div.name-suggestion.mt-1 > div > div:nth-child(43)");
      if (ad2) await page.evaluate(el => el.remove(), ad2);

      // 直接获取所有目标元素,摆脱固定索引依赖
      await page.waitForSelector("div.name-suggestion.mt-1 div.nsg__name_meaning a");
      const nameElements = await page.$$("div.name-suggestion.mt-1 div.nsg__name_meaning a");

      // 遍历元素收集数据
      for (const el of nameElements) {
        const fullName = await page.evaluate(el => el.textContent.trim(), el);
        if (fullName) { // 过滤空值
          data.push({ fullName });
        }
      }

      console.log(`第${pageNumber}页已收集,当前总数据量:${data.length}`);
    } catch (err) {
      console.error(`第${pageNumber}页爬取失败:`, err);
    }
  }

  await browser.close();
})();

app.get("/", (req, res) => {
  res.status(200).json(data);
});

app.listen(3000, () => {
  console.log("App is running on port 3000...");
});

关键优化点

  1. 容错处理弹窗与广告:先判断元素是否存在再执行操作,避免因元素缺失导致的流程中断。
  2. 放弃固定索引定位:直接通过目标元素的特征选择器获取所有元素,不受DOM结构变化影响。
  3. 可靠的页面加载等待:使用waitUntil: "networkidle2"替代固定延时,确保页面资源加载完成。
  4. 错误捕获机制:添加try/catch处理单页爬取失败的情况,避免某一页出错导致整个爬取终止。
  5. 数据过滤:添加空值过滤,避免无效数据进入结果数组。

内容的提问来源于stack exchange,提问作者Konidoni Ravirr

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 20:22:51