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

使用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页面的初始化逻辑。

具体修复步骤

  1. 提前注入覆盖代码
    将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);
      }
    });
    
  2. 优化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"
      }
    }
    
  3. 调整Puppeteer启动参数
    添加--disable-site-isolation-trials参数,避免页面隔离导致注入失效:

    const browser = await puppeteer.launch({
      executablePath: chromePath,
      args: [
        // ... 原有参数 ...
        '--disable-site-isolation-trials'
      ],
      // ... 原有配置 ...
    });
    
  4. 替换注入方式
    如果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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 14:47:14