使用PKG编译后page.evaluateOnNewDocument功能失效问题
PKG编译后Puppeteer覆盖localStorage功能失效问题
直接通过node index.js运行代码时,能够成功覆盖window.localStorage,让Google无法访问该存储对象;但经PKG编译为可执行文件后,这个覆盖效果完全失效。
核心代码
const puppeteer = require('puppeteer-extra'); const StealthPlugin = require('puppeteer-extra-plugin-stealth'); const findChrome = require('chrome-finder'); const moment = require('moment-timezone'); const UserAgent = require('user-agents'); const stealth = StealthPlugin(); puppeteer.use(stealth); initialization(); async function initialization() { const chromePath = findChrome(); const browser = await puppeteer.launch({ executablePath: chromePath, args: [ '--no-sandbox', '--disable-infobars', '--disable-setuid-sandbox', '--disable-extensions', '--disable-dev-shm-usage', '--disable-gpu', '--lang=en', '--window-position=0,0', '--test-type', '--disable-features=site-per-process', '--ignore-certificate-errors', // '--auto-open-devtools-for-tabs', ], headless: false, ignoreDefaultArgs: ['--enable-automation', '--mute-audio'], ignoreHTTPSErrors: true, }); browser.on('targetcreated', async target => { try { if (target.type() === 'page') { const newPage = await target.page(); newPage && newPage.on('framenavigated', async frame => { try { const newURL = frame?.url(); if (newURL && newURL.includes('https://www.example.com')) { const allTimezones = moment.tz.names(); const randomTimezoneIndex = Math.floor( Math.random() * allTimezones.length ); const randomTimezone = allTimezones[randomTimezoneIndex]; const ua = new UserAgent({}); const { userAgent, viewportWidth, viewportHeight, platform } = ua.data; await newPage.setUserAgent(userAgent); await newPage.setViewport({ width: viewportWidth, height: viewportHeight, }); await newPage.emulateTimezone(randomTimezone); await newPage.setBypassCSP(true); await newPage.evaluateOnNewDocument(() => { console.log('window', window); Object.defineProperty(window, 'localStorage', { value: { getItem: () => null, setItem: () => null, removeItem: () => null, clear: () => null, }, writable: false, configurable: false, enumerable: true, }); }); await newPage.goto('https://www.google.com'); } } catch (error) { console.log('framenavigated err', error.message); } }); } } catch (error) { console.log('targetcreated err', error.message); } }); const page = await browser.newPage(); await page.goto('https://www.example.com'); }
package.json脚本配置
{ "scripts": { "pkg": "pkg ./src/index.js -c ./pkgConfig.json" } }
pkgConfig.json配置
{ "pkg": { "assets": [ "node_modules/chrome-finder/**/*", "node_modules/moment-timezone/**/*", "node_modules/puppeteer/**/*", "node_modules/puppeteer-core/**/*", "node_modules/puppeteer-extra/**/*", "node_modules/puppeteer-extra-plugin-stealth/**/*", "node_modules/user-agents/**/*" ], "outputPath": "dist/build" } }
问题分析与解决方法
核心原因
PKG编译后,Puppeteer的evaluateOnNewDocument脚本注入时机可能被环境干扰,或者打包过程中遗漏了部分依赖资源,导致覆盖代码无法在页面脚本执行前生效;另外,页面导航事件的监听逻辑在编译后的环境中可能存在延迟,使得覆盖操作晚于Google页面的初始化逻辑。
具体修复步骤
提前注入覆盖代码
将evaluateOnNewDocument的调用移到页面创建后立即执行,而不是等待framenavigated事件。比如在targetcreated事件中拿到newPage后直接注入:browser.on('targetcreated', async target => { try { if (target.type() === 'page') { const newPage = await target.page(); if (newPage) { // 提前注入localStorage覆盖代码 await newPage.evaluateOnNewDocument(() => { Object.defineProperty(window, 'localStorage', { value: { getItem: () => null, setItem: () => null, removeItem: () => null, clear: () => null, }, writable: false, configurable: false, enumerable: true, }); }); // 原有的framenavigated逻辑保留 newPage.on('framenavigated', async frame => { // ... 原有代码 ... }); } } } catch (error) { console.log('targetcreated err', error.message); } });优化PKG资源打包配置
在pkgConfig.json中补充更具体的Puppeteer相关资源路径,确保注入脚本被完整打包:{ "pkg": { "assets": [ "node_modules/chrome-finder/**/*", "node_modules/moment-timezone/**/*", "node_modules/puppeteer/**/*.js", "node_modules/puppeteer-core/**/*.js", "node_modules/puppeteer-extra/**/*.js", "node_modules/puppeteer-extra-plugin-stealth/**/*.js", "node_modules/user-agents/**/*.js", "node_modules/puppeteer-extra-plugin-stealth/**/*.json" ], "outputPath": "dist/build" } }调整Puppeteer启动参数
添加--disable-site-isolation-trials参数,避免页面隔离导致注入失效:const browser = await puppeteer.launch({ executablePath: chromePath, args: [ // ... 原有参数 ... '--disable-site-isolation-trials' ], // ... 原有配置 ... });替换注入方式
如果evaluateOnNewDocument仍然失效,改用page.evaluate在goto之前同步执行覆盖代码:// 在newPage.goto('https://www.google.com')之前添加 await newPage.evaluate(() => { Object.defineProperty(window, 'localStorage', { value: { getItem: () => null, setItem: () => null, removeItem: () => null, clear: () => null, }, writable: false, configurable: false, enumerable: true, }); });
内容的提问来源于stack exchange,提问作者Maksym
相关产品推荐
相关产品推荐

