You need to enable JavaScript to run this app. 如何在Puppeteer爬虫中正确禁用JavaScript 解决生效失败与hook报错问题
优惠活动
大模型
产品
解决方案
定价
更多

如何在Puppeteer爬虫中正确禁用JavaScript 解决生效失败与hook报错问题

报错根因与JS禁用失效问题解决

报错直接原因

你之前hook newPage 触发的TypeError,是因为当前使用的Puppeteer版本中,Browser类不在包的顶层导出属性上,直接访问puppeteer.Browser得到的是undefined,自然无法读取其.prototype属性。

JS禁用不生效的核心问题

  • 时机滞后:原来的逻辑在targetcreated事件触发、页面已经开始加载后,才调用setJavaScriptEnabled、挂载请求拦截,首屏的初始脚本请求已经发出、浏览器已经识别到JS环境可用,<noscript>标签自然不会生效。
  • 逻辑冗余:同时调用了setJavaScriptEnabled和请求拦截abort script,但两个动作都没赶在页面导航前执行,等于白写。

修正后的稳定实现

不需要全局hook Puppeteer原型,利用原生API就能从页面创建的最早时机完成JS禁用配置,保证<noscript>标签正常触发:

import puppeteer, { Target } from "puppeteer";
import _ from "lodash";

abstract class BaseCrawler {
  public static readonly TOR_PATH = process.env.TOR_PATH ?? "";
  public static readonly TOR_PROFILE_PATH = process.env.TOR_PROFILE_PATH ?? "";
  public static readonly TORRC_PATH = process.env.TORRC_PATH;
  public static headless = false;
  public readonly browser: Promise<puppeteer.Browser>;
  private readonly jsEnabled: boolean;

  public async activePage(timeout = 30_000): Promise<puppeteer.Page | null> {
    const browser = await this.browser;
    const start = new Date().getTime();
    while (new Date().getTime() - start < timeout) {
      const pages = await browser.pages();
      const visiblePages = [];
      for (const p of pages) {
        if (await p.evaluate(() => document.visibilityState === "visible")) {
          visiblePages.push(p);
        }
      }
      if (visiblePages.length === 1) return visiblePages[0];
    }
    return null;
  }

  constructor(jsEnabled = false, website = "https://check.torproject.org") {
    this.jsEnabled = jsEnabled;
    this.browser = puppeteer.launch({
      headless: BaseCrawler.headless,
      args: ["--proxy-server=socks5://127.0.0.1:9050"],
      userDataDir: "./.headless-data",
    });

    this.browser.then(async (b) => {
      b.on("targetcreated", async (e: Target) => {
        const page = await e.page();
        if (!page) return;
        // 跳过浏览器内部页,不修改内部页配置
        if (page.url().startsWith("chrome://")) return;

        // 在页面发起任何导航请求前,先设置JS状态
        await page.setJavaScriptEnabled(this.jsEnabled);
        // 设置Tor风格UA
        await page.setUserAgent(
          `Mozilla/5.0 (Windows NT 10.0; rv:78.0) Gecko/20100101 Firefox/${_.random(60, 100)}.0`
        );
        // 提前开启请求拦截,在页面发请求前就挂载逻辑
        await page.setRequestInterception(true);
        page.on("request", (request) => {
          // 当JS禁用时,直接中止所有脚本资源请求,避免漏网的内联脚本执行
          if (!this.jsEnabled && request.resourceType() === "script") {
            return request.abort();
          }
          request.continue();
        });
      });

      // 修正原代码重复新建页面的问题,直接创建页访问目标地址
      const page = await b.newPage();
      await page.goto(website, { waitUntil: "domcontentloaded" });
    });
  }
}

export class TorWindow extends BaseCrawler {}

实现效果说明

  • JS状态由浏览器引擎层面直接控制,不是单纯拦截脚本加载的模拟效果,网站可真实识别到JS已关闭,<noscript>标签可正常渲染
  • 所有后续新建的页面都会自动应用统一的JS配置,不需要重复编写相同逻辑
  • 完全规避了之前需要访问puppeteer.Browser.prototype的hack逻辑,兼容不同Puppeteer版本的导出结构,不会再触发类未定义的报错

内容的提问来源于stack exchange,提问作者The epic face 007

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.26 18:45:04