You need to enable JavaScript to run this app. Puppeteer调用browser.close()无法自动关闭浏览器问题求助
优惠活动
大模型
产品
解决方案
定价
更多

Puppeteer调用browser.close()无法自动关闭浏览器问题求助

问题根源

  • 递归函数getData多处等待操作设置了timeout: 0,一旦某一页加载异常、谷歌触发人机验证、或者分页到最后没有匹配的yuRUbf选择器时,函数会进入无限等待状态,永远不会返回结果,后续的browser.close()和打印逻辑根本不会执行。你手动关闭浏览器后,所有页面操作会抛出连接中断错误,递归链路才会终止,因此只有手动关浏览器后才会输出爬取数据。
  • 你使用的谷歌搜索URL携带了固定的临时会话参数(sxsrf、ei等),这些参数有有效期,翻页到一定次数后会失效,导致返回的页面结构和预期不符,触发waitForSelector无限等待。
  • 错误捕获分支没有返回值,一旦某层递归触发异常,会导致递归链路断裂卡住,无法正常返回结果。

修复方案

  1. 给所有等待操作设置合理的超时时间,避免无限等待
  2. 错误捕获分支明确返回空数组,保证递归链路始终可以正常结束
  3. 改用不带临时会话参数的通用谷歌搜索URL,避免参数过期问题
  4. 增加分页深度限制,避免无意义的无限递归

修复后代码

const puppeteer = require("puppeteer");

(async () => {
  const getData = async (url, start = 0) => {
    // 增加最大分页限制,最多爬10页,可按需调整
    if (start > 100) return []
    try {
      const page = await browser.newPage();
      await page.setViewport({ width: 1366, height: 768 });

      const query = `${url}&start=${start}`;
      // 超时时间设为30秒,可按需调整
      await page.goto(query, { waitUntil: "load", timeout: 30000 });

      await page.waitForSelector('div[class="yuRUbf"] > a', { timeout: 30000 });
      const links = await page.evaluate(() =>
        Array.from(document.querySelectorAll('div[class="yuRUbf"] > a')).map(
          (a) => a.href
        )
      );
      await page.close();
      if (links.length < 1) {
        return links;
      } else {
        return links.concat(await getData(url, start + 10));
      }
    } catch (error) {
      console.log("爬取异常:", error);
      // 异常分支返回空数组,保证递归逻辑正常结束
      return []
    }
  };

  const browser = await puppeteer.launch({ headless: false });

  // 移除临时会话参数,使用通用搜索URL
  const url = "https://www.google.com/search?q=Let+You+Love+Me+by+Rita+Ora";

  const allLinks = await getData(url);
  await browser.close();
  console.log("爬取到的所有链接:", allLinks);
})();

内容的提问来源于stack exchange,提问作者Ali Raza

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.18 13:54:04