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

Puppeteer中'TimeoutError is not defined'及后续类型错误排查求助

Puppeteer中'TimeoutError is not defined'及后续类型错误排查求助

问题分析

从你的代码和报错来看,核心问题有两个:

  1. TimeoutError无全局定义:Puppeteer的TimeoutError并不是全局可用的,必须从你导入的puppeteer实例的errors属性中获取,直接使用会提示未定义。
  2. 变量作用域导致puppeteer未初始化:你在代码顶部声明了let puppeteer;,但实际在main函数里才执行require赋值,而scrape函数在main外部,当scrape执行时puppeteer变量还是undefined,所以访问puppeteer.errors就会触发Cannot read properties of undefined的错误。

修复方案

我们可以通过调整导入位置、修正作用域,以及正确引用错误类来解决问题:

1. 提前正确导入Puppeteer

把Puppeteer的require移到代码最顶部,确保在所有函数定义前就完成导入,这样所有函数都能访问到正确的puppeteer实例:

// 提前导入依赖,确保作用域覆盖所有使用的函数
const puppeteer = require('puppeteer-extra');
const stealthPlugin = require('puppeteer-extra-plugin-stealth');
puppeteer.use(stealthPlugin());

// **************************************** constants
// all error codes that we pass back
const ERROR_CODE_URL_INVALID = 1002;
const ERROR_INTERNAL_SERVER_ERROR = 1003;
const ERROR_TIMEOUT = 1004;

2. 正确引用TimeoutError

在catch块中,使用puppeteer.errors.TimeoutError来判断错误类型,此时puppeteer已经完成初始化,不会再出现未定义的问题:

catch (error) {
  // 现在可以正常访问puppeteer.errors下的TimeoutError
  if (error instanceof puppeteer.errors.TimeoutError) {
    errorContent = ERROR_TIMEOUT;
  } else {
    throw error;
  }
}

3. 额外的小细节修复

原代码里还有两个容易被忽略的小问题,一起修复可以避免更多意外:

  • throw response.text;要改成throw await response.text();,因为response.text()是异步函数,直接抛函数引用没有实际错误信息。
  • page.mouse.click(1, 1);是异步操作,需要加上await,否则会在点击未完成时就执行后续的evaluate,可能导致弹窗未关闭就爬取内容。

完整修复后的SSCCE示例

// 提前导入依赖,确保作用域正确
const puppeteer = require('puppeteer-extra');
const stealthPlugin = require('puppeteer-extra-plugin-stealth');
puppeteer.use(stealthPlugin());

// **************************************** constants
// all error codes that we pass back
const ERROR_CODE_URL_INVALID = 1002;
const ERROR_INTERNAL_SERVER_ERROR = 1003;
const ERROR_TIMEOUT = 1004;

// **************************************** scrape
const scrape = async (page, url) => {
  let response = null;
  let errorContent = null;

  try {
    // 故意设置短超时来测试问题
    response = await page.goto(url, { waitUntil: 'load', timeout: 100 });
    
    if (!response) {
      response = await page.waitForResponse(() => true, { timeout: 100 });
    }

    if (response.status() === 200) {
      // 成功,无需额外操作
    } else if (response.status() === 404) {
      errorContent = ERROR_CODE_URL_INVALID;
    } else if (response.status() === 500) {
      errorContent = ERROR_INTERNAL_SERVER_ERROR;
    } else {
      // 抛出实际的响应文本作为错误信息
      throw await response.text();
    }
  } catch (error) {
    // 正确引用Puppeteer的TimeoutError
    if (error instanceof puppeteer.errors.TimeoutError) {
      errorContent = ERROR_TIMEOUT;
    } else {
      throw error;
    }
  }

  if (errorContent !== null) {
    throw errorContent;
  }

  // 等待点击操作完成
  await page.mouse.click(1, 1);

  // 获取页面HTML
  const data = await page.evaluate(() => document.querySelector('*').outerHTML);
  return data;
};

// **************************************** main
let browser;
(async function main() {
  browser = await puppeteer.launch({ headless: false });
  const [page] = await browser.pages();
  
  try {
    let s = await scrape(page, "https://www.scrapethissite.com/pages/");
    console.log(s);
  } catch (err) {
    console.log("爬取错误:", err);
  }
})()
.catch(err => console.log("全局错误:", err))
.finally(() => browser?.close());

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 10:08:02