如何在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
相关产品推荐
相关产品推荐

